diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-04-16 17:25:09 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-04-16 17:25:09 +0200 |
commit | c9b3ea785346546948afcf685c80c460f3b1317a (patch) | |
tree | e5e43c24167f8e0a4d66e776ea71219e6e3d4adc /src | |
parent | 914f8f335d73c4dd69b72f6f2d8c53257bce497d (diff) |
POTD skeleton #10.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/forward.c | 65 | ||||
-rw-r--r-- | src/forward.h | 32 | ||||
-rw-r--r-- | src/main.c | 35 | ||||
-rw-r--r-- | src/server.c | 39 | ||||
-rw-r--r-- | src/server.h | 21 | ||||
-rw-r--r-- | src/server_ssh.c | 20 | ||||
-rw-r--r-- | src/server_ssh.h | 13 | ||||
-rw-r--r-- | src/socket.c | 59 | ||||
-rw-r--r-- | src/socket.h | 11 |
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 @@ -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 |