]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
reopen and move of get_option to util.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Feb 2010 16:40:22 +0000 (16:40 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Feb 2010 16:40:22 +0000 (16:40 +0000)
git-svn-id: file:///svn/unbound/trunk@1989 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/remote.c
doc/Changelog
doc/unbound-control.8.in
smallapp/unbound-checkconf.c
smallapp/unbound-control.c
util/config_file.c
util/config_file.h
util/fptr_wlist.c
util/fptr_wlist.h
util/netevent.c

index b77e4198b6a14a7ef41ed9f3871144d21c95fac7..03767d49df13460a54236dda45bde58c9c29c787 100644 (file)
@@ -1460,6 +1460,15 @@ do_dump_requestlist(SSL* ssl, struct worker* worker)
        }
 }
 
+/** do the log_reopen command */
+static void
+do_log_reopen(SSL* ssl, struct worker* worker)
+{
+       struct config_file* cfg = worker->env.cfg;
+       send_ok(ssl);
+       log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
+}
+
 /** tell other processes to execute the command */
 void
 distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
@@ -1553,6 +1562,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
                do_flush_name(ssl, worker, skipwhite(p+5));
        } else if(strncmp(p, "dump_requestlist", 16) == 0) {
                do_dump_requestlist(ssl, worker);
+       } else if(strncmp(p, "log_reopen", 10) == 0) {
+               do_log_reopen(ssl, worker);
        } else {
                (void)ssl_printf(ssl, "error unknown command '%s'\n", p);
        }
index ad3cbca2bb948c55d620b23197669dac5fcccbdb..b4b1ae7e68e6b1a8ab26974ae14e8b39c680a689 100644 (file)
@@ -4,6 +4,9 @@
          is backed off to.
        - RD flag not enabled for dnssec-blacklisted tries, unless necessary.
        - pickup ldns compile fix, libdl for libcrypto.
+       - log 'tcp connect: connection timed out' only in high verbosity.
+       - unbound-control log_reopen command.
+       - moved get_option code from unbound-checkconf to util/config_file.c
 
 17 February 2010: Wouter
        - Disregard DNSKEY from authority section for chain of trust.
index e3c0e0138f9ffea029f16f415fd95eccd347b24d..06434140a04e5272a2a587d0d4dc24eee3355a55 100644 (file)
@@ -57,6 +57,11 @@ Change verbosity value for logging. Same values as \fBverbosity\fR keyword in
 \fIunbound.conf\fR(5).  This new setting lasts until the server is issued
 a reload (taken from config file again), or the next verbosity control command.
 .TP
+.B log_reopen
+Reopen the logfile, close and open it.  Useful for logrotation to make the
+daemon release the file it is logging to.  If you are using syslog it will
+attempt to close and open the syslog (which may not work if chrooted).
+.TP
 .B stats
 Print statistics. Resets the internal counters to zero, this can be 
 controlled using the \fBstatistics\-cumulative\fR config statement. 
index 97e9ce213c2ff5908f07e55e4f49a6b02b946f3e..f48088ae2aebfdbe536a50556ffffc0dcefe4286 100644 (file)
@@ -80,40 +80,6 @@ usage()
        exit(1);
 }
 
-/** compare and print decimal option */
-#define O_DEC(opt, str, var) if(strcmp(opt, str)==0) \
-       {printf("%d\n", (int)cfg->var);}
-/** compare and print unsigned option */
-#define O_UNS(opt, str, var) if(strcmp(opt, str)==0) \
-       {printf("%u\n", (unsigned)cfg->var);}
-/** compare and print yesno option */
-#define O_YNO(opt, str, var) if(strcmp(opt, str)==0) \
-       {printf("%s\n", cfg->var?"yes":"no");}
-/** compare and print string option */
-#define O_STR(opt, str, var) if(strcmp(opt, str)==0) \
-       {printf("%s\n", cfg->var?cfg->var:"");}
-/** compare and print array option */
-#define O_IFC(opt, str, num, arr) if(strcmp(opt, str)==0) \
-       {int i; for(i=0; i<cfg->num; i++) printf("%s\n", cfg->arr[i]);}
-/** 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; \
-         printf("%u%6.6u\n", (unsigned)f, (unsigned)b); \
-       } else printf("%u\n", (unsigned)cfg->var);}
-/** 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) \
-               printf("%s\n", p->str); \
-       }
-/** 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) \
-               printf("%s %s\n", p->str, p->str2); \
-       }
-
 /** 
  * Print given option to stdout 
  * @param cfg: config
@@ -123,98 +89,8 @@ usage()
 static void
 print_option(struct config_file* cfg, const char* opt)
 {
-       O_DEC(opt, "verbosity", verbosity)
-       else O_DEC(opt, "statistics-interval", stat_interval)
-       else O_YNO(opt, "statistics-cumulative", stat_interval)
-       else O_YNO(opt, "extended-statistics", stat_extended)
-       else O_DEC(opt, "num-threads", num_threads)
-       else O_IFC(opt, "interface", num_ifs, ifs)
-       else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs)
-       else O_YNO(opt, "interface-automatic", if_automatic)
-       else O_DEC(opt, "port", port)
-       else O_DEC(opt, "outgoing-range", outgoing_num_ports)
-       else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp)
-       else O_DEC(opt, "incoming-num-tcp", incoming_num_tcp)
-       else O_DEC(opt, "edns-buffer-size", edns_buffer_size)
-       else O_DEC(opt, "msg-buffer-size", msg_buffer_size)
-       else O_MEM(opt, "msg-cache-size", msg_cache_size)
-       else O_DEC(opt, "msg-cache-slabs", msg_cache_slabs)
-       else O_DEC(opt, "num-queries-per-thread", num_queries_per_thread)
-       else O_UNS(opt, "jostle-timeout", jostle_time)
-       else O_MEM(opt, "so-rcvbuf", socket_rcvbuf)
-       else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
-       else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
-       else O_YNO(opt, "prefetch-key", prefetch_key)
-       else O_YNO(opt, "prefetch", prefetch)
-       else O_DEC(opt, "cache-max-ttl", max_ttl)
-       else O_DEC(opt, "infra-host-ttl", host_ttl)
-       else O_DEC(opt, "infra-lame-ttl", lame_ttl)
-       else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs)
-       else O_MEM(opt, "infra-cache-numhosts", infra_cache_numhosts)
-       else O_MEM(opt, "infra-cache-lame-size", infra_cache_lame_size)
-       else O_YNO(opt, "do-ip4", do_ip4)
-       else O_YNO(opt, "do-ip6", do_ip6)
-       else O_YNO(opt, "do-udp", do_udp)
-       else O_YNO(opt, "do-tcp", do_tcp)
-       else O_YNO(opt, "do-daemonize", do_daemonize)
-       else O_STR(opt, "chroot", chrootdir)
-       else O_STR(opt, "username", username)
-       else O_STR(opt, "directory", directory)
-       else O_STR(opt, "logfile", logfile)
-       else O_STR(opt, "pidfile", pidfile)
-       else O_YNO(opt, "hide-identity", hide_identity)
-       else O_YNO(opt, "hide-version", hide_version)
-       else O_STR(opt, "identity", identity)
-       else O_STR(opt, "version", version)
-       else O_STR(opt, "target-fetch-policy", target_fetch_policy)
-       else O_YNO(opt, "harden-short-bufsize", harden_short_bufsize)
-       else O_YNO(opt, "harden-large-queries", harden_large_queries)
-       else O_YNO(opt, "harden-glue", harden_glue)
-       else O_YNO(opt, "harden-dnssec-stripped", harden_dnssec_stripped)
-       else O_YNO(opt, "harden-referral-path", harden_referral_path)
-       else O_YNO(opt, "use-caps-for-id", use_caps_bits_for_id)
-       else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold)
-       else O_YNO(opt, "do-not-query-localhost", donotquery_localhost)
-       else O_STR(opt, "module-config", module_conf)
-       else O_STR(opt, "dlv-anchor-file", dlv_anchor_file)
-       else O_DEC(opt, "val-bogus-ttl", bogus_ttl)
-       else O_YNO(opt, "val-clean-additional", val_clean_additional)
-       else O_DEC(opt, "val-log-level", val_log_level)
-       else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
-       else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
-       else O_UNS(opt, "add-holddown", add_holddown)
-       else O_UNS(opt, "del-holddown", del_holddown)
-       else O_UNS(opt, "keep-missing", keep_missing)
-       else O_MEM(opt, "key-cache-size", key_cache_size)
-       else O_DEC(opt, "key-cache-slabs", key_cache_slabs)
-       else O_MEM(opt, "neg-cache-size", neg_cache_size)
-       else O_YNO(opt, "control-enable", remote_control_enable)
-       else O_DEC(opt, "control-port", control_port)
-       else O_STR(opt, "server-key-file", server_key_file)
-       else O_STR(opt, "server-cert-file", server_cert_file)
-       else O_STR(opt, "control-key-file", control_key_file)
-       else O_STR(opt, "control-cert-file", control_cert_file)
-       else O_LST(opt, "root-hints", root_hints)
-       else O_LS2(opt, "access-control", acls)
-       else O_LST(opt, "do-not-query-address", donotqueryaddrs)
-       else O_LST(opt, "private-address", private_address)
-       else O_LST(opt, "private-domain", private_domain)
-       else O_LST(opt, "auto-trust-anchor-file", auto_trust_anchor_file_list)
-       else O_LST(opt, "trust-anchor-file", trust_anchor_file_list)
-       else O_LST(opt, "trust-anchor", trust_anchor_list)
-       else O_LST(opt, "trusted-keys-file", trusted_keys_file_list)
-       else O_LST(opt, "dlv-anchor", dlv_anchor_list)
-       else O_LST(opt, "control-interface", control_ifs)
-       else O_UNS(opt, "val-override-date", val_date_override)
-       /* not here:
-        * outgoing-permit, outgoing-avoid - have list of ports
-        * local-zone - zones and nodefault variables
-        * local-data - see below
-        * local-data-ptr - converted to local-data entries
-        * stub-zone, name, stub-addr, stub-host, stub-prime
-        * forward-zone, name, forward-addr, forward-host
-        */
-       else fatal_exit("cannot print option '%s'", opt);
+       if(!config_get_option(cfg, opt, config_print_func, stdout))
+               fatal_exit("cannot print option '%s'", opt);
 }
 
 /** check if module works with config */
index 07760cde0b434cd3fc568d7f017c970b68432dea..b60fb231ff20027e0de66a098f5b90ed8a21a89a 100644 (file)
@@ -66,6 +66,7 @@ usage()
        printf("  stats_noreset                 peek at statistics\n");
        printf("  status                        display status of server\n");
        printf("  verbosity <number>            change logging detail\n");
+       printf("  log_reopen                    close and open the logfile\n");
        printf("  local_zone <name> <type>      add new local zone\n");
        printf("  local_zone_remove <name>      remove local zone and its contents\n");
        printf("  local_data <RR data...>       add local data, for example\n");
index 0fb0ef6a8548322116c258af1d0b2ebf9d03a1e5..e3a3bf92f264f6bd15e2a22d343959e0441ed201 100644 (file)
@@ -49,6 +49,7 @@
 #include "util/data/msgparse.h"
 #include "util/module.h"
 #include "util/regional.h"
+#include "util/fptr_wlist.h"
 #include "util/data/dname.h"
 /** global config during parsing */
 struct config_parser_state* cfg_parser = 0;
@@ -467,6 +468,152 @@ int config_set_option(struct config_file* cfg, const char* opt,
        return 1;
 }
 
+/** 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; i<cfg->num; 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\n", (unsigned)f, (unsigned)b); \
+       } else snprintf(buf, len, "%u\n", (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\n", p->str, p->str2); \
+               func(buf, arg); \
+       }
+
+void config_print_func(char* line, void* arg)
+{
+       FILE* f = (FILE*)arg;
+       (void)fprintf(f, "%s\n", line);
+}
+
+int
+config_get_option(struct config_file* cfg, const char* opt, 
+       void (*func)(char*,void*), void* arg)
+{
+       char buf[1024];
+       size_t len = sizeof(buf);
+       fptr_whitelist_print_func(func);
+       O_DEC(opt, "verbosity", verbosity)
+       else O_DEC(opt, "statistics-interval", stat_interval)
+       else O_YNO(opt, "statistics-cumulative", stat_interval)
+       else O_YNO(opt, "extended-statistics", stat_extended)
+       else O_DEC(opt, "num-threads", num_threads)
+       else O_IFC(opt, "interface", num_ifs, ifs)
+       else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs)
+       else O_YNO(opt, "interface-automatic", if_automatic)
+       else O_DEC(opt, "port", port)
+       else O_DEC(opt, "outgoing-range", outgoing_num_ports)
+       else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp)
+       else O_DEC(opt, "incoming-num-tcp", incoming_num_tcp)
+       else O_DEC(opt, "edns-buffer-size", edns_buffer_size)
+       else O_DEC(opt, "msg-buffer-size", msg_buffer_size)
+       else O_MEM(opt, "msg-cache-size", msg_cache_size)
+       else O_DEC(opt, "msg-cache-slabs", msg_cache_slabs)
+       else O_DEC(opt, "num-queries-per-thread", num_queries_per_thread)
+       else O_UNS(opt, "jostle-timeout", jostle_time)
+       else O_MEM(opt, "so-rcvbuf", socket_rcvbuf)
+       else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
+       else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
+       else O_YNO(opt, "prefetch-key", prefetch_key)
+       else O_YNO(opt, "prefetch", prefetch)
+       else O_DEC(opt, "cache-max-ttl", max_ttl)
+       else O_DEC(opt, "infra-host-ttl", host_ttl)
+       else O_DEC(opt, "infra-lame-ttl", lame_ttl)
+       else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs)
+       else O_MEM(opt, "infra-cache-numhosts", infra_cache_numhosts)
+       else O_MEM(opt, "infra-cache-lame-size", infra_cache_lame_size)
+       else O_YNO(opt, "do-ip4", do_ip4)
+       else O_YNO(opt, "do-ip6", do_ip6)
+       else O_YNO(opt, "do-udp", do_udp)
+       else O_YNO(opt, "do-tcp", do_tcp)
+       else O_YNO(opt, "do-daemonize", do_daemonize)
+       else O_STR(opt, "chroot", chrootdir)
+       else O_STR(opt, "username", username)
+       else O_STR(opt, "directory", directory)
+       else O_STR(opt, "logfile", logfile)
+       else O_STR(opt, "pidfile", pidfile)
+       else O_YNO(opt, "hide-identity", hide_identity)
+       else O_YNO(opt, "hide-version", hide_version)
+       else O_STR(opt, "identity", identity)
+       else O_STR(opt, "version", version)
+       else O_STR(opt, "target-fetch-policy", target_fetch_policy)
+       else O_YNO(opt, "harden-short-bufsize", harden_short_bufsize)
+       else O_YNO(opt, "harden-large-queries", harden_large_queries)
+       else O_YNO(opt, "harden-glue", harden_glue)
+       else O_YNO(opt, "harden-dnssec-stripped", harden_dnssec_stripped)
+       else O_YNO(opt, "harden-referral-path", harden_referral_path)
+       else O_YNO(opt, "use-caps-for-id", use_caps_bits_for_id)
+       else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold)
+       else O_YNO(opt, "do-not-query-localhost", donotquery_localhost)
+       else O_STR(opt, "module-config", module_conf)
+       else O_STR(opt, "dlv-anchor-file", dlv_anchor_file)
+       else O_DEC(opt, "val-bogus-ttl", bogus_ttl)
+       else O_YNO(opt, "val-clean-additional", val_clean_additional)
+       else O_DEC(opt, "val-log-level", val_log_level)
+       else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
+       else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
+       else O_UNS(opt, "add-holddown", add_holddown)
+       else O_UNS(opt, "del-holddown", del_holddown)
+       else O_UNS(opt, "keep-missing", keep_missing)
+       else O_MEM(opt, "key-cache-size", key_cache_size)
+       else O_DEC(opt, "key-cache-slabs", key_cache_slabs)
+       else O_MEM(opt, "neg-cache-size", neg_cache_size)
+       else O_YNO(opt, "control-enable", remote_control_enable)
+       else O_DEC(opt, "control-port", control_port)
+       else O_STR(opt, "server-key-file", server_key_file)
+       else O_STR(opt, "server-cert-file", server_cert_file)
+       else O_STR(opt, "control-key-file", control_key_file)
+       else O_STR(opt, "control-cert-file", control_cert_file)
+       else O_LST(opt, "root-hints", root_hints)
+       else O_LS2(opt, "access-control", acls)
+       else O_LST(opt, "do-not-query-address", donotqueryaddrs)
+       else O_LST(opt, "private-address", private_address)
+       else O_LST(opt, "private-domain", private_domain)
+       else O_LST(opt, "auto-trust-anchor-file", auto_trust_anchor_file_list)
+       else O_LST(opt, "trust-anchor-file", trust_anchor_file_list)
+       else O_LST(opt, "trust-anchor", trust_anchor_list)
+       else O_LST(opt, "trusted-keys-file", trusted_keys_file_list)
+       else O_LST(opt, "dlv-anchor", dlv_anchor_list)
+       else O_LST(opt, "control-interface", control_ifs)
+       else O_UNS(opt, "val-override-date", val_date_override)
+       /* not here:
+        * outgoing-permit, outgoing-avoid - have list of ports
+        * local-zone - zones and nodefault variables
+        * local-data - see below
+        * local-data-ptr - converted to local-data entries
+        * stub-zone, name, stub-addr, stub-host, stub-prime
+        * forward-zone, name, forward-addr, forward-host
+        */
+       else return 0;
+       return 1;
+}
+
 /** initialize the global cfg_parser object */
 static void
 create_cfg_parser(struct config_file* cfg, char* filename, const char* chroot)
index 83565c925034ec530b62f245644addd54298c992..fb136346ec8a67f42c3b2a2520006f90788c6faf 100644 (file)
@@ -361,6 +361,25 @@ void config_apply(struct config_file* config);
 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);
+
+/**
+ * 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);
+
 /**
  * Insert string into strlist.
  * @param head: pointer to strlist head variable.
index f973c6becaefcf78f501f8f0c38017995b573060..f77e98674eb67af3d23e91ede75e2087c2ea2a1f 100644 (file)
@@ -70,6 +70,7 @@
 #include "libunbound/libworker.h"
 #include "libunbound/context.h"
 #include "util/tube.h"
+#include "util/config_file.h"
 #ifdef UB_ON_WINDOWS
 #include "winrc/win_svc.h"
 #endif
@@ -388,3 +389,9 @@ int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr)
        else if(fptr == &probe_answer_cb) return 1;
        return 0;
 }
+
+int fptr_whitelist_print_func(void (*fptr)(char*,void*))
+{
+       if(fptr == &config_print_func) return 1;
+       return 0;
+}
index 4338b2fb7d06e9944a67735e8807b31df766208c..331626df4cc354cdcae82fdda9e8147182f879f4 100644 (file)
@@ -316,6 +316,13 @@ int fptr_whitelist_tube_listen(tube_callback_t* fptr);
  */
 int fptr_whitelist_mesh_cb(mesh_cb_func_t 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*));
+
 /** Due to module breakage by fptr wlist, these test app declarations
  * are presented here */
 /** 
index 2891dfe95122d795bd3a18491101c141b1f63644..2f2635744e93ee3cf2b34726b2f5d1e14cbfc3ce 100644 (file)
@@ -852,6 +852,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
 #ifdef EHOSTDOWN
                 else if(error == EHOSTDOWN && verbosity < 2)
                         return 0; /* silence 'host is down' */
+#endif
+#ifdef ETIMEDOUT
+                else if(error == ETIMEDOUT && verbosity < 2)
+                        return 0; /* silence 'connection timed out' */
 #endif
                 else if(error != 0) {
                        log_err("tcp connect: %s", strerror(error));