Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ if BUILD_PROXY
gssproxy_SOURCES = \
src/gp_config.c \
src/gp_init.c \
src/gp_mgmt.c \
src/gp_socket.c \
src/gp_workers.c \
src/gp_creds.c \
Expand Down
2 changes: 2 additions & 0 deletions src/gp_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <stdio.h>
#include <time.h>

#define GP_INFO_DEBUG_LVL 1

extern int gp_debug;

void gp_debug_toggle(int);
Expand Down
260 changes: 240 additions & 20 deletions src/gp_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,42 +113,262 @@ void fini_server(void)
closelog();
}

verto_ctx *init_event_loop(void)
static struct gp_service *
find_service_by_name(struct gp_config *cfg, const char *name)
{
verto_ctx *vctx;
int i;
struct gp_service *ret = NULL;

for (i = 0; i < cfg->num_svcs; i++) {
if (strcmp(cfg->svcs[i]->name, name) == 0) {
ret = cfg->svcs[i];
break;
}
}
return ret;
}

const int vflags =
VERTO_EV_FLAG_PERSIST |
VERTO_EV_FLAG_IO_READ |
VERTO_EV_FLAG_IO_CLOSE_FD;

static verto_ev *setup_socket(struct gssproxy_ctx *gpctx, char *sock_name,
bool with_activation)
{
struct gp_sock_ctx *sock_ctx = NULL;
verto_ev *ev;

vctx = verto_default(NULL,
VERTO_EV_TYPE_IO |
VERTO_EV_TYPE_SIGNAL |
VERTO_EV_TYPE_TIMEOUT);
if (!vctx) {
#ifdef HAVE_SYSTEMD_DAEMON
if (with_activation) {
int ret;
/* try to se if available, fallback otherwise */
ret = init_activation_socket(gpctx, sock_name, &sock_ctx);
if (ret) {
return NULL;
}
}
#endif
if (!sock_ctx) {
/* no activation, try regular socket creation */
sock_ctx = init_unix_socket(gpctx, sock_name);
}
if (!sock_ctx) {
return NULL;
}

ev = verto_add_signal(vctx, VERTO_EV_FLAG_PERSIST, break_loop, SIGINT);
ev = verto_add_io(gpctx->vctx, vflags, accept_sock_conn, sock_ctx->fd);
if (!ev) {
verto_free(vctx);
free(sock_ctx);
return NULL;
}
ev = verto_add_signal(vctx, VERTO_EV_FLAG_PERSIST, break_loop, SIGTERM);

verto_set_private(ev, sock_ctx, free_unix_socket);
return ev;
}

int init_sockets(struct gssproxy_ctx *gpctx, struct gp_config *old_config)
{
int i;
struct gp_sock_ctx *sock_ctx;
verto_ev *ev;
struct gp_service *svc;

/* init main socket */
if (!old_config) {
ev = setup_socket(gpctx, gpctx->config->socket_name, false);
if (!ev) {
return 1;
}

gpctx->sock_ev = ev;
} else if (strcmp(old_config->socket_name,
gpctx->config->socket_name) != 0) {
ev = setup_socket(gpctx, gpctx->config->socket_name, false);
if (!ev) {
return 1;
}

verto_del(gpctx->sock_ev);
gpctx->sock_ev = ev;
} else {
/* free_config will erase the socket name; update it accordingly */
sock_ctx = verto_get_private(gpctx->sock_ev);
sock_ctx->socket = gpctx->config->socket_name;
}

/* propagate any sockets that shouldn't change */
if (old_config) {
for (i = 0; i < old_config->num_svcs; i++) {
if (old_config->svcs[i]->ev) {
svc = find_service_by_name(gpctx->config,
old_config->svcs[i]->name);
if (svc &&
((svc->socket == old_config->svcs[i]->socket) ||
((svc->socket != NULL) &&
(old_config->svcs[i]->socket != NULL) &&
strcmp(svc->socket,
old_config->svcs[i]->socket) == 0))) {
svc->ev = old_config->svcs[i]->ev;
sock_ctx = verto_get_private(svc->ev);
sock_ctx->socket = svc->socket;
} else {
verto_del(old_config->svcs[i]->ev);
}
}
}
}

/* init all other sockets */
for (i = 0; i < gpctx->config->num_svcs; i++) {
svc = gpctx->config->svcs[i];
if (svc->socket != NULL && svc->ev == NULL) {
ev = setup_socket(gpctx, svc->socket, false);
if (!ev) {
return 1;
}
svc->ev = ev;
}
}
return 0;
}

int init_userproxy_socket(struct gssproxy_ctx *gpctx)
{
verto_ev *ev;

/* init main socket */
ev = setup_socket(gpctx, gpctx->config->socket_name, true);
if (!ev) {
verto_free(vctx);
return NULL;
return 1;
}
ev = verto_add_signal(vctx, VERTO_EV_FLAG_PERSIST, break_loop, SIGQUIT);

gpctx->sock_ev = ev;
return 0;
}

static void hup_handler(verto_ctx *vctx UNUSED, verto_ev *ev)
{
int ret;
struct gssproxy_ctx *gpctx;
struct gp_config *new_config, *old_config;

gpctx = verto_get_private(ev);

GPDEBUG("Received SIGHUP; re-reading config.\n");
new_config = read_config(gpctx->config_file, gpctx->config_dir,
gpctx->config_socket, gpctx->daemonize);
if (!new_config) {
GPERROR("Error reading new configuration on SIGHUP; keeping old "
"configuration instead!\n");
return;
}
old_config = gpctx->config;
gpctx->config = new_config;

ret = init_sockets(gpctx, old_config);
if (ret != 0) {
exit(ret);
}

/* conditionally reload kernel interface */
init_proc_nfsd(gpctx->config);

free_config(&old_config);

GPDEBUG("New config loaded successfully.\n");
return;
}

static void break_loop(verto_ctx *vctx, verto_ev *ev UNUSED)
{
GPDEBUG("Exiting after receiving a signal\n");
verto_break(vctx);
}

void init_event_loop(struct gssproxy_ctx *gpctx)
{
verto_ev *ev;

gpctx->vctx = verto_default(NULL,
VERTO_EV_TYPE_IO |
VERTO_EV_TYPE_SIGNAL |
VERTO_EV_TYPE_TIMEOUT);
if (!gpctx->vctx) {
goto fail;
}

ev = verto_add_signal(gpctx->vctx, VERTO_EV_FLAG_PERSIST,
break_loop, SIGINT);
if (!ev) {
verto_free(vctx);
return NULL;
fprintf(stderr, "Failed to register SIGINT handler\n");
goto fail;
}
ev = verto_add_signal(vctx, VERTO_EV_FLAG_PERSIST, VERTO_SIG_IGN, SIGPIPE);
ev = verto_add_signal(gpctx->vctx, VERTO_EV_FLAG_PERSIST,
break_loop, SIGTERM);
if (!ev) {
verto_free(vctx);
return NULL;
fprintf(stderr, "Failed to register SIGTERM handler\n");
goto fail;
}
ev = verto_add_signal(gpctx->vctx, VERTO_EV_FLAG_PERSIST,
break_loop, SIGQUIT);
if (!ev) {
fprintf(stderr, "Failed to register SIGQUIT handler\n");
goto fail;
}
ev = verto_add_signal(gpctx->vctx, VERTO_EV_FLAG_PERSIST,
VERTO_SIG_IGN, SIGPIPE);
if (!ev) {
fprintf(stderr, "Failed to register SIGPIPE handler\n");
goto fail;
}
if (gpctx->userproxymode) {
ev = verto_add_signal(gpctx->vctx, VERTO_EV_FLAG_PERSIST,
VERTO_SIG_IGN, SIGHUP);
} else {
ev = verto_add_signal(gpctx->vctx, VERTO_EV_FLAG_PERSIST,
hup_handler, SIGHUP);
if (ev) verto_set_private(ev, gpctx, NULL);
}
if (!ev) {
fprintf(stderr, "Failed to register SIGHUP handler\n");
goto fail;
}

return;

fail:
if (gpctx->vctx) {
verto_free(gpctx->vctx);
gpctx->vctx = NULL;
}
}

/* Schedule an event to run as soon as the event loop is started
* This is also useful in debugging to know that all initialization
* is done. */
static void delayed_init(verto_ctx *vctx UNUSED, verto_ev *ev)
{
struct gssproxy_ctx *gpctx;

GPDEBUG("Initialization complete.\n");

gpctx = verto_get_private(ev);
idle_handler(gpctx);
}

int init_event_fini(struct gssproxy_ctx *gpctx)
{
verto_ev *ev;

ev = verto_add_timeout(gpctx->vctx, VERTO_EV_FLAG_NONE, delayed_init, 1);
if (!ev) {
fprintf(stderr, "Failed to register delayed_init event!\n");
return EXIT_FAILURE;
}
/* SIGHUP handler added in main */
verto_set_private(ev, gpctx, NULL);

return vctx;
return 0;
}

void init_proc_nfsd(struct gp_config *cfg)
Expand Down
69 changes: 69 additions & 0 deletions src/gp_mgmt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* Copyright (C) 2022 the GSS-PROXY contributors, see COPYING for license */

#include "config.h"
#include "gp_proxy.h"
#include <time.h>

static void idle_terminate(verto_ctx *vctx, verto_ev *ev)
{
struct gssproxy_ctx *gpctx = verto_get_private(ev);

GPDEBUG("Terminating, after idling for %ld seconds!\n",
(long)gpctx->term_timeout/1000);
verto_break(vctx);
}

void idle_handler(struct gssproxy_ctx *gpctx)
{
/* we've been called, this means some event just fired,
* restart the timeout handler */

if (gpctx->term_timeout == 0) {
/* self termination is disabled */
return;
}

verto_del(gpctx->term_ev);

/* Add self-termination timeout */
gpctx->term_ev = verto_add_timeout(gpctx->vctx, VERTO_EV_FLAG_NONE,
idle_terminate, gpctx->term_timeout);
if (!gpctx->term_ev) {
GPDEBUG("Failed to register timeout event!\n");
}
verto_set_private(gpctx->term_ev, gpctx, NULL);
}

void gp_activity_accounting(struct gssproxy_ctx *gpctx,
ssize_t rb, ssize_t wb)
{
time_t now = time(NULL);

if (rb) {
/* Gssproxy received some request */
gpctx->readstats += rb;
GPDEBUGN(GP_INFO_DEBUG_LVL, "Total received bytes: %ld\n",
(long)gpctx->readstats);

/* receiving bytes is also a sign of activity,
* reset idle event */
idle_handler(gpctx);

GPDEBUGN(GP_INFO_DEBUG_LVL, "Idle for: %ld seconds\n",
now - gpctx->last_activity);
gpctx->last_activity = now;
}

if (wb) {
gpctx->writestats += wb;
GPDEBUGN(GP_INFO_DEBUG_LVL, "Total sent bytes: %ld\n",
(long)gpctx->writestats);

/* sending bytes is also a sign of activity, but we send
* bytes only in response to requests and this is already
* captured by a previous read event, just update the
* last_activity counter to have a more precise info messgae
* on the following read */
gpctx->last_activity = now;
}
}
Loading