diff --git a/common.c b/common.c index bff10be..0814246 100644 --- a/common.c +++ b/common.c @@ -87,6 +87,12 @@ int start_listen_sockets(int *sockfd[], struct addrinfo *addr_list) res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)); check_res_dumpdie(res, addr, "setsockopt(SO_REUSEADDR)"); + if (addr->ai_flags & SO_KEEPALIVE) { + res = setsockopt((*sockfd)[i], SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one)); + check_res_dumpdie(res, addr, "setsockopt(SO_KEEPALIVE)"); + printf("set up keepalive\n"); + } + if (IP_FREEBIND) { res = setsockopt((*sockfd)[i], IPPROTO_IP, IP_FREEBIND, (char*)&one, sizeof(one)); check_res_dumpdie(res, addr, "setsockopt(IP_FREEBIND)"); diff --git a/example.cfg b/example.cfg index d28372f..371bcf0 100644 --- a/example.cfg +++ b/example.cfg @@ -14,10 +14,11 @@ pidfile: "/var/run/sslh.pid"; # List of interfaces on which we should listen +# Options: listen: ( { host: "thelonious"; port: "443"; }, - { host: "thelonious"; port: "8080"; } + { host: "thelonious"; port: "8080"; keepalive: true; } ); # List of protocols @@ -28,6 +29,10 @@ listen: # service: (optional) libwrap service name (see hosts_access(5)) # host, port: where to connect when this probe succeeds +# log_level: 0 to turn off logging +# 1 to log each incoming connection +# keepalive: Should TCP keepalive be on or off for that +# connection (default is off) # # Probe-specific options: # tls: @@ -48,7 +53,7 @@ listen: protocols: ( - { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; }, + { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; }, { name: "http"; host: "localhost"; port: "80"; }, # match BOTH ALPN/SNI diff --git a/sslh-main.c b/sslh-main.c index 5b47fe4..220a867 100644 --- a/sslh-main.c +++ b/sslh-main.c @@ -2,7 +2,7 @@ # main: processing of config file, command line options and start the main # loop. # -# Copyright (C) 2007-2014 Yves Rutschle +# Copyright (C) 2007-2016 Yves Rutschle # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public @@ -133,7 +133,10 @@ static void printsettings(void) } fprintf(stderr, "listening on:\n"); for (a = addr_listen; a; a = a->ai_next) { - fprintf(stderr, "\t%s\n", sprintaddr(buf, sizeof(buf), a)); + fprintf(stderr, + "\t%s\t[keepalive: %d]\n", + sprintaddr(buf, sizeof(buf), a), + a->ai_flags & SO_KEEPALIVE ? 1 : 0); } fprintf(stderr, "timeout: %d\non-timeout: %s\n", probing_timeout, timeout_protocol()->description); @@ -147,7 +150,7 @@ static void printsettings(void) static int config_listen(config_t *config, struct addrinfo **listen) { config_setting_t *setting, *addr; - int len, i; + int len, i, keepalive; const char *hostname, *port; setting = config_lookup(config, "listen"); @@ -163,12 +166,20 @@ static int config_listen(config_t *config, struct addrinfo **listen) return -1; } + keepalive = 0; + config_setting_lookup_bool(addr, "keepalive", &keepalive); + resolve_split_name(listen, hostname, port); /* getaddrinfo returned a list of addresses corresponding to the * specification; move the pointer to the end of that list before - * processing the next specification */ - for (; *listen; listen = &((*listen)->ai_next)); + * processing the next specification, while setting flags for + * start_listen_sockets() through ai_flags (which is not meant for + * that, but is only used as hint in getaddrinfo, so it's OK) */ + for (; *listen; listen = &((*listen)->ai_next)) { + if (keepalive) + (*listen)->ai_flags = SO_KEEPALIVE; + } } }