aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2018-04-16 17:25:09 +0200
committerToni Uhlig <matzeton@googlemail.com>2018-04-16 17:25:09 +0200
commitc9b3ea785346546948afcf685c80c460f3b1317a (patch)
treee5e43c24167f8e0a4d66e776ea71219e6e3d4adc /src
parent914f8f335d73c4dd69b72f6f2d8c53257bce497d (diff)
POTD skeleton #10.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/forward.c65
-rw-r--r--src/forward.h32
-rw-r--r--src/main.c35
-rw-r--r--src/server.c39
-rw-r--r--src/server.h21
-rw-r--r--src/server_ssh.c20
-rw-r--r--src/server_ssh.h13
-rw-r--r--src/socket.c59
-rw-r--r--src/socket.h11
10 files changed, 231 insertions, 68 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6545722..b26f216 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
-AM_CFLAGS = -pedantic -Wall -std=gnu99 -D_GNU_SOURCE=1 $(libssh_CFLAGS)
+AM_CFLAGS = -pedantic -Wall -std=gnu99 -fstrict-aliasing -D_GNU_SOURCE=1 $(libssh_CFLAGS)
AM_LDFLAGS = $(libssh_LIBS)
sbin_PROGRAMS = potd
-potd_SOURCES = main.c utils.c log.c log_colored.c socket.c server.c server_ssh.c
+potd_SOURCES = utils.c log.c log_colored.c socket.c forward.c server.c server_ssh.c main.c
diff --git a/src/forward.c b/src/forward.c
new file mode 100644
index 0000000..16fec1a
--- /dev/null
+++ b/src/forward.c
@@ -0,0 +1,65 @@
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "forward.h"
+#include "log.h"
+
+
+int fwd_init_ctx(forward_ctx **ctx, init_cb init_fn)
+{
+ assert(ctx || init_fn);
+ if (!*ctx)
+ *ctx = (forward_ctx *) malloc(sizeof(**ctx));
+ assert(*ctx);
+
+ memset(*ctx, 0, sizeof(**ctx));
+ if (init_fn(*ctx))
+ return 1;
+
+ return 0;
+}
+
+int fwd_setup(forward_ctx *ctx, const char *host, const char *port)
+{
+ int s;
+ struct addrinfo *fwd_addr = NULL;
+
+ assert(ctx);
+
+ s = socket_init_in(host, port, &fwd_addr);
+ if (s) {
+ E_GAIERR(s, "Could not initialise forward socket");
+ return 1;
+ }
+ if (!ctx->fwd_cbs.on_listen)
+ return 1;
+ if (ctx->fwd_cbs.on_listen(ctx))
+ return 1;
+ if (socket_connect_in(&ctx->sock, fwd_addr)) {
+ E_STRERR("Could not connect forward socket");
+ return 1;
+ }
+ s = socket_addrtostr_in(&ctx->sock, ctx->host_buf, ctx->service_buf);
+ if (s) {
+ E_GAIERR(s, "Convert forward socket address to string");
+ return 1;
+ }
+ if (socket_close(&ctx->sock)) {
+ E_STRERR("Forward socket close");
+ return 1;
+ }
+
+ return 0;
+}
+
+int fwd_validate_ctx(const forward_ctx *ctx)
+{
+ assert(ctx);
+ assert(ctx->fwd_cbs.on_listen && ctx->fwd_cbs.on_shutdown);
+ assert(ctx->sock.addr_len > 0);
+ assert(strnlen(ctx->host_buf, NI_MAXHOST) > 0);
+ assert(strnlen(ctx->service_buf, NI_MAXSERV) > 0);
+
+ return 0;
+}
diff --git a/src/forward.h b/src/forward.h
new file mode 100644
index 0000000..f98d331
--- /dev/null
+++ b/src/forward.h
@@ -0,0 +1,32 @@
+#ifndef POTD_FORWARD_H
+#define POTD_FORWARD_H 1
+
+#include "socket.h"
+
+struct forward_ctx;
+
+typedef int (*init_cb) (struct forward_ctx *ctx);
+typedef int (*on_listen_cb) (struct forward_ctx *ctx);
+typedef int (*on_shutdown_cb) (struct forward_ctx *ctx);
+
+typedef struct fwd_callbacks {
+ on_listen_cb on_listen;
+ on_shutdown_cb on_shutdown;
+} fwd_callbacks;
+
+typedef struct forward_ctx {
+ pthread_t self;
+ fwd_callbacks fwd_cbs;
+ psocket sock;
+ char host_buf[NI_MAXHOST], service_buf[NI_MAXSERV];
+ void *data;
+} forward_ctx;
+
+
+int fwd_init_ctx(forward_ctx **ctx, init_cb init_fn);
+
+int fwd_setup(forward_ctx *ctx, const char *host, const char *port);
+
+int fwd_validate_ctx(const forward_ctx *ctx);
+
+#endif
diff --git a/src/main.c b/src/main.c
index 21dcc5f..963be84 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,6 +2,7 @@
#include "log_colored.h"
#include "server.h"
#include "server_ssh.h"
+#include "forward.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -12,15 +13,24 @@ int main(int argc, char *argv[])
const size_t srv_siz = 3;
const char *ssh_ports[srv_siz];
server_ctx *srv[srv_siz];
- struct addrinfo *netifs = NULL;
+ forward_ctx *ssh_fwd = NULL;
int epoll_fd;
- (void)argc;
- (void)argv;
+ (void) argc;
+ (void) argv;
LOG_SET_FUNCS_VA(LOG_COLORED_FUNCS);
N("%s (C) 2018 Toni Uhlig (%s)", PACKAGE_STRING, PACKAGE_BUGREPORT);
+ {
+ ABORT_ON_FATAL( fwd_init_ctx(&ssh_fwd, ssh_init_cb),
+ "Forwarder initialisation" );
+ ABORT_ON_FATAL( fwd_setup(ssh_fwd, "127.0.0.1", "22"),
+ "Forwarder setup" );
+ ABORT_ON_FATAL( fwd_validate_ctx( ssh_fwd ),
+ "Forwarder validation" );
+ }
+
memset(srv, 0, sizeof(srv));
ssh_ports[0] = "2222";
ssh_ports[1] = "2223";
@@ -29,21 +39,12 @@ int main(int argc, char *argv[])
for (size_t i = 0; i < srv_siz; ++i) {
D("Initialising redirector service on port %s", ssh_ports[i]);
- ABORT_ON_FATAL( server_init_ctx(&srv[i], ssh_init_cb) == 0,
+ ABORT_ON_FATAL( server_init_ctx(&srv[i], ssh_fwd),
"Server initialisation" );
- server_validate_ctx(srv[i]);
-
- GAI_ABORT_ON_FATAL( socket_init_in(NULL, ssh_ports[i], &netifs),
- "Socket initialisation" );
-
- ABORT_ON_FATAL( socket_bind_in(&srv[i]->sock, netifs),
- "Socket bind" );
-
- ABORT_ON_FATAL( socket_listen_in(&srv[i]->sock),
- "Socket listen" );
-
- ABORT_ON_FATAL( srv[i]->server_cbs.on_listen(&srv[i]->server_dat),
- "Socket on listen callback" );
+ ABORT_ON_FATAL( server_setup(srv[i], NULL, ssh_ports[i]),
+ "Server setup" );
+ ABORT_ON_FATAL( server_validate_ctx(srv[i]),
+ "Server validation" );
}
D2("%s", "Server epoll setup");
diff --git a/src/server.c b/src/server.c
index 884ec5b..01ad6c9 100644
--- a/src/server.c
+++ b/src/server.c
@@ -24,24 +24,51 @@ client_mainloop_epoll(void *arg);
static int client_io_epoll(struct epoll_event *ev);
-int server_init_ctx(server_ctx **ctx, init_cb init_fn)
+int server_init_ctx(server_ctx **ctx, forward_ctx *fwd_ctx)
{
- assert(ctx);
+ assert(ctx && fwd_ctx);
if (!*ctx)
*ctx = (server_ctx *) malloc(sizeof(**ctx));
- assert(*ctx || init_fn);
+ assert(*ctx);
memset(*ctx, 0, sizeof(**ctx));
- if (!init_fn(*ctx))
+ (*ctx)->fwd_ctx = fwd_ctx;
+
+ return 0;
+}
+
+int server_setup(server_ctx *ctx,
+ const char *listen_addr, const char *listen_port)
+{
+ int s;
+ struct addrinfo *srv_addr = NULL;
+
+ assert(ctx);
+ assert(listen_addr || listen_port);
+
+ D2("Try to listen on %s:%s", listen_addr, listen_port);
+ s = socket_init_in(listen_addr, listen_port, &srv_addr);
+ if (s) {
+ E_GAIERR(s, "Could not initialise server socket");
return 1;
+ }
+ if (socket_bind_in(&ctx->sock, srv_addr)) {
+ E_STRERR("Could not bind server socket");
+ return 1;
+ }
+ if (socket_listen_in(&ctx->sock)) {
+ E_STRERR("Could not listen on server socket");
+ return 1;
+ }
return 0;
}
int server_validate_ctx(const server_ctx *ctx)
{
- assert(ctx);
- assert(ctx->server_cbs.on_listen && ctx->server_cbs.on_shutdown);
+ assert(ctx && ctx->fwd_ctx);
+ assert(ctx->sock.fd >= 0 && ctx->sock.addr_len > 0);
+
return 0;
}
diff --git a/src/server.h b/src/server.h
index 07ca93b..2460507 100644
--- a/src/server.h
+++ b/src/server.h
@@ -2,33 +2,22 @@
#define POTD_SERVER_H 1
#include "socket.h"
+#include "forward.h"
#define POTD_MAXFD 32
#define POTD_MAXEVENTS 64
-typedef struct server_data {
- void *data;
-} server_data;
-
-typedef int (*on_listen_cb) (struct server_data *data);
-typedef int (*on_shutdown_cb) (struct server_data *data);
-
-typedef struct server_callbacks {
- on_listen_cb on_listen;
- on_shutdown_cb on_shutdown;
-} server_callbacks;
-
typedef struct server_ctx {
- server_callbacks server_cbs;
- server_data server_dat;
+ forward_ctx *fwd_ctx;
psocket sock;
char host_buf[NI_MAXHOST], service_buf[NI_MAXSERV];
} server_ctx;
-typedef int (*init_cb) (struct server_ctx *ctx);
+int server_init_ctx(server_ctx **ctx, forward_ctx *fwd_ctx);
-int server_init_ctx(server_ctx **ctx, init_cb init_fn);
+int server_setup(server_ctx *ctx,
+ const char *listen_addr, const char *listen_port);
int server_validate_ctx(const server_ctx *ctx);
diff --git a/src/server_ssh.c b/src/server_ssh.c
index 9f24657..219866b 100644
--- a/src/server_ssh.c
+++ b/src/server_ssh.c
@@ -4,10 +4,14 @@
#include <libssh/server.h>
#include "server_ssh.h"
-#include "server.h"
#include "log.h"
-struct server_callbacks potd_ssh_callbacks = {
+typedef struct ssh_data {
+ ssh_bind sshbind;
+ ssh_session session;
+} ssh_data;
+
+struct fwd_callbacks potd_ssh_callbacks = {
.on_listen = ssh_on_listen,
.on_shutdown = ssh_on_shutdown
};
@@ -16,9 +20,9 @@ static int set_default_keys(ssh_bind sshbind, int rsa_already_set,
int dsa_already_set, int ecdsa_already_set);
-int ssh_init_cb(struct server_ctx *ctx)
+int ssh_init_cb(struct forward_ctx *ctx)
{
- ctx->server_cbs = potd_ssh_callbacks;
+ ctx->fwd_cbs = potd_ssh_callbacks;
if (ssh_init())
return 1;
@@ -26,7 +30,7 @@ int ssh_init_cb(struct server_ctx *ctx)
assert(d);
d->sshbind = ssh_bind_new();
d->session = ssh_new();
- ctx->server_dat.data = d;
+ ctx->data = d;
if (!d->sshbind || !d->session)
return 1;
if (set_default_keys(d->sshbind, 0, 0, 0))
@@ -35,9 +39,9 @@ int ssh_init_cb(struct server_ctx *ctx)
return 0;
}
-int ssh_on_listen(struct server_data *data)
+int ssh_on_listen(struct forward_ctx *ctx)
{
- ssh_data *d = (ssh_data *) data->data;
+ ssh_data *d = (ssh_data *) ctx->data;
if (ssh_bind_listen(d->sshbind) < 0) {
E("Error listening to SSH socket: %s", ssh_get_error(d->sshbind));
@@ -45,7 +49,7 @@ int ssh_on_listen(struct server_data *data)
return 0;
}
-int ssh_on_shutdown(struct server_data *data)
+int ssh_on_shutdown(struct forward_ctx *ctx)
{
return 0;
}
diff --git a/src/server_ssh.h b/src/server_ssh.h
index e057814..e0744f8 100644
--- a/src/server_ssh.h
+++ b/src/server_ssh.h
@@ -4,17 +4,12 @@
#include <libssh/server.h>
#include "server.h"
+#include "forward.h"
-typedef struct ssh_data {
- ssh_bind sshbind;
- ssh_session session;
-} ssh_data;
+int ssh_init_cb(struct forward_ctx *ctx);
+int ssh_on_listen(struct forward_ctx *ctx);
-int ssh_init_cb(struct server_ctx *ctx);
-
-int ssh_on_listen(struct server_data *data);
-
-int ssh_on_shutdown(struct server_data *data);
+int ssh_on_shutdown(struct forward_ctx *ctx);
#endif
diff --git a/src/socket.c b/src/socket.c
index b666eb1..7b16254 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -23,19 +23,19 @@ static int socket_nonblock(const psocket *psock)
return 0;
}
-int socket_init_in(const char *listen_addr,
- const char *listen_port, struct addrinfo **results)
+int socket_init_in(const char *addr,
+ const char *port, struct addrinfo **results)
{
struct addrinfo hints;
- assert(listen_addr || listen_port); /* getaddrinfo wants either node or service */
+ assert(addr || port); /* getaddrinfo wants either node or service */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* IPV4 && IPV6 */
hints.ai_socktype = SOCK_STREAM; /* TCP */
hints.ai_flags = AI_PASSIVE; /* all interfaces */
- return getaddrinfo(listen_addr, listen_port, &hints, results);
+ return getaddrinfo(addr, port, &hints, results);
}
int socket_bind_in(psocket *psock, struct addrinfo *results)
@@ -58,11 +58,13 @@ int socket_bind_in(psocket *psock, struct addrinfo *results)
if (!rp)
return -1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(int)) < 0)
- return -2;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(int));
psock->fd = fd;
psock->addr_len = rp->ai_addrlen;
psock->addr = *rp->ai_addr;
+ psock->family = rp->ai_family;
+ psock->socktype = rp->ai_socktype;
+ psock->protocol = rp->ai_protocol;
freeaddrinfo(results);
return socket_nonblock(psock);
}
@@ -112,12 +114,15 @@ int socket_connect_in(psocket *psock, struct addrinfo *results)
if (!rp)
return -1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(int)) < 0)
- return -2;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(int));
psock->fd = fd;
psock->addr_len = rp->ai_addrlen;
psock->addr = *rp->ai_addr;
+ psock->family = rp->ai_family;
+ psock->socktype = rp->ai_socktype;
+ psock->protocol = rp->ai_protocol;
freeaddrinfo(results);
+
return socket_nonblock(psock);
}
@@ -132,5 +137,43 @@ int socket_addrtostr_in(const psocket *psock,
&hbuf[0], NI_MAXHOST,
&sbuf[0], NI_MAXSERV,
NI_NUMERICHOST | NI_NUMERICSERV);
+
return s;
}
+
+int socket_reconnect_in(psocket *psock)
+{
+ int rv;
+ int reuse_enable = 1;
+
+ assert(psock);
+ if (psock->fd >= 0)
+ return -1;
+
+ psock->fd = socket(psock->family, psock->socktype, psock->protocol);
+ if (psock->fd < 0)
+ return -2;
+ rv = connect(psock->fd, &psock->addr, psock->addr_len);
+ if (!rv) {
+ socket_close(psock);
+ return -3;
+ }
+
+ if (setsockopt(psock->fd, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(int)) < 0) {
+ socket_close(psock);
+ return -4;
+ }
+
+ return 0;
+}
+
+int socket_close(psocket *psock)
+{
+ int rv;
+
+ assert(psock);
+ rv = close(psock->fd);
+ psock->fd = -1;
+
+ return rv;
+}
diff --git a/src/socket.h b/src/socket.h
index cdc556a..861a8b3 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -9,11 +9,14 @@ typedef struct psocket {
int fd;
socklen_t addr_len;
struct sockaddr addr;
+ int family;
+ int socktype;
+ int protocol;
} psocket;
-int socket_init_in(const char *listen_addr,
- const char *listen_port, struct addrinfo **results);
+int socket_init_in(const char *addr,
+ const char *port, struct addrinfo **results);
int socket_bind_in(psocket *psock, struct addrinfo *results);
@@ -26,4 +29,8 @@ int socket_connect_in(psocket *psock, struct addrinfo *results);
int socket_addrtostr_in(const psocket *psock,
char hbuf[NI_MAXHOST], char sbuf[NI_MAXSERV]);
+int socket_reconnect_in(psocket *psock);
+
+int socket_close(psocket *psock);
+
#endif