made echosrv independant from common.o and with its own configuration

This commit is contained in:
yrutschle 2021-04-24 10:31:41 +02:00
parent 4c570e8d57
commit c3d019284d
3 changed files with 195 additions and 8 deletions

View File

@ -80,7 +80,7 @@ sslh: sslh-fork sslh-select
$(OBJS): version.h common.h collection.h sslh-conf.h gap.h
sslh-conf.c: sslhconf.cfg
sslh-conf.c sslh-conf.h: sslhconf.cfg
conf2struct sslhconf.cfg
sslh-fork: version.h $(OBJS) sslh-fork.o Makefile
@ -94,8 +94,11 @@ sslh-select: version.h $(OBJS) sslh-select.o Makefile
systemd-sslh-generator: systemd-sslh-generator.o
$(CC) $(CFLAGS) $(LDFLAGS) -o systemd-sslh-generator systemd-sslh-generator.o -lconfig
echosrv: version.h $(OBJS) echosrv.o
$(CC) $(CFLAGS) $(LDFLAGS) -o echosrv echosrv.o sslh-conf.o probe.o common.o tls.o argtable3.o $(LIBS)
echosrv-conf.c echosrv-conf.h: echosrv.cfg
conf2struct echosrv.cfg
echosrv: version.h echosrv-conf.c echosrv.o echosrv-conf.o argtable3.o
$(CC) $(CFLAGS) $(LDFLAGS) -o echosrv echosrv.o echosrv-conf.o argtable3.o $(LIBS)
$(MAN): sslh.pod Makefile
pod2man --section=8 --release=$(VERSION) --center=" " sslh.pod | gzip -9 - > $(MAN)

157
echosrv.c
View File

@ -27,9 +27,13 @@
#include <syslog.h>
#include <libgen.h>
#include <getopt.h>
#include <errno.h>
#define cfg sslhcfg
#include "common.h"
#include "sslh-conf.h"
#undef cfg
#include "echosrv-conf.h"
/* Added to make the code compilable under CYGWIN
* */
@ -37,7 +41,24 @@
#define SA_NOCLDWAIT 0
#endif
const char* server_type = "echsrv"; /* keep setup_syslog happy */
struct echocfg_item cfg;
void check_res_dump(int res, struct addrinfo *addr, char* syscall)
{
char buf[NI_MAXHOST];
if (res == -1) {
if (addr)
fprintf(stderr, "error %s:%s: %s\n",
sprintaddr(buf, sizeof(buf), addr),
syscall,
strerror(errno));
else
fprintf(stderr, "Dying just because\n");
exit(1);
}
}
void start_echo(int fd)
{
@ -80,7 +101,7 @@ void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen)
while (1)
{
in_socket = accept(listen_sockets[i].socketfd, 0, 0);
if (cfg.verbose) fprintf(stderr, "accepted fd %d\n", in_socket);
CHECK_RES_DIE(in_socket, "accept");
if (!fork())
{
@ -95,6 +116,132 @@ void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen)
wait(NULL);
}
/* Following is a number of utility functions copied from common.c: linking
* against common.o directly means echosrv has to work with sslh config struct,
* which makes it all too awkward */
/* simplified from common.c */
char* sprintaddr(char* buf, size_t size, struct addrinfo *a)
{
char host[NI_MAXHOST], serv[NI_MAXSERV];
int res;
res = getnameinfo(a->ai_addr, a->ai_addrlen,
host, sizeof(host),
serv, sizeof(serv),
0 );
if (res) {
/* Name resolution failed: do it numerically instead */
res = getnameinfo(a->ai_addr, a->ai_addrlen,
host, sizeof(host),
serv, sizeof(serv),
NI_NUMERICHOST | NI_NUMERICSERV);
/* should not fail but... */
if (res) {
strcpy(host, "?");
strcpy(serv, "?");
}
}
snprintf(buf, size, "%s:%s", host, serv);
return buf;
}
/* simplified from common.c */
int listen_single_addr(struct addrinfo* addr, int keepalive, int udp)
{
struct sockaddr_storage *saddr;
int sockfd, one, res;
saddr = (struct sockaddr_storage*)addr->ai_addr;
sockfd = socket(saddr->ss_family, udp ? SOCK_DGRAM : SOCK_STREAM, 0);
check_res_dump(sockfd, addr, "socket");
one = 1;
res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one));
check_res_dump(res, addr, "setsockopt(SO_REUSEADDR)");
if (addr->ai_addr->sa_family == AF_INET6) {
res = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one));
check_res_dump(res, addr, "setsockopt(IPV6_V6ONLY)");
}
res = bind(sockfd, addr->ai_addr, addr->ai_addrlen);
check_res_dump(res, addr, "bind");
if (!udp) {
res = listen (sockfd, 50);
check_res_dump(res, addr, "listen");
}
return sockfd;
}
/* simplified from common.c */
int resolve_split_name(struct addrinfo **out, char* host, char* serv)
{
struct addrinfo hint;
char *end;
int res;
memset(&hint, 0, sizeof(hint));
hint.ai_family = PF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
/* If it is a RFC-Compliant IPv6 address ("[1234::12]:443"), remove brackets
* around IP address */
if (host[0] == '[') {
end = strrchr(host, ']');
if (!end) {
fprintf(stderr, "%s: no closing bracket in IPv6 address?\n", host);
return -1;
}
host++; /* skip first bracket */
*end = 0; /* remove last bracket */
}
res = getaddrinfo(host, serv, &hint, out);
if (res)
fprintf(stderr, "%s `%s:%s'\n", gai_strerror(res), host, serv);
return res;
}
int start_listen_sockets(struct listen_endpoint *sockfd[])
{
struct addrinfo *addr, *start_addr;
char buf[NI_MAXHOST];
int i, res;
int num_addr = 0, keepalive = 0, udp = 0;
*sockfd = NULL;
fprintf(stderr, "Listening to:\n");
for (i = 0; i < cfg.listen_len; i++) {
udp = cfg.udp;
res = resolve_split_name(&start_addr, cfg.listen[i].host, cfg.listen[i].port);
if (res) exit(4);
for (addr = start_addr; addr; addr = addr->ai_next) {
num_addr++;
*sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd));
(*sockfd)[num_addr-1].socketfd = listen_single_addr(addr, keepalive, udp);
(*sockfd)[num_addr-1].type = udp ? SOCK_DGRAM : SOCK_STREAM;
fprintf(stderr, "%d:\t%s\n", (*sockfd)[num_addr-1].socketfd, sprintaddr(buf, sizeof(buf), addr));
}
freeaddrinfo(start_addr);
}
return num_addr;
}
int main(int argc, char *argv[])
{
@ -105,10 +252,10 @@ int main(int argc, char *argv[])
struct listen_endpoint *listen_sockets;
memset(&cfg, 0, sizeof(cfg));
if (sslhcfg_cl_parse(argc, argv, &cfg))
if (echocfg_cl_parse(argc, argv, &cfg))
exit(1);
sslhcfg_fprint(stdout, &cfg, 0);
echocfg_fprint(stdout, &cfg, 0);
num_addr_listen = start_listen_sockets(&listen_sockets);

37
echosrv.cfg Normal file
View File

@ -0,0 +1,37 @@
# conf2struct for echosrv
header: "echosrv-conf.h";
parser: "echosrv-conf.c";
printer: true;
conffile_option: ("F", "config");
config: {
name: "echocfg",
type: "list",
items: (
{name: "udp", type: "bool"; default: false; },
{name: "prefix", type: "string"; },
{ name: "listen",
type: "list",
items: (
{ name: "host"; type: "string"; var: true; },
{ name: "port"; type: "string"; var: true; }
)
}
)
}
cl_groups: (
{ name: "listen"; pattern: "(.+):(\w+)"; description: "Listen on host:port";
short: "p"; argdesc: "<host:port>";
list: "listen";
# no override, this just adds to the list (and thus can be specified several times)
targets: (
{ path: "host"; value: "$1" },
{ path: "port"; value: "$2" }
);
}
)