|
Packit Service |
9f2c4a |
/* Copyright (C) 2011,2015 the GSS-PROXY contributors, see COPYING for license */
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
#include "config.h"
|
|
Packit Service |
9f2c4a |
#include <stdlib.h>
|
|
Packit Service |
9f2c4a |
#include "popt.h"
|
|
Packit Service |
9f2c4a |
#include "gp_proxy.h"
|
|
Packit Service |
9f2c4a |
#include <signal.h>
|
|
Packit Service |
9f2c4a |
#include <string.h>
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
const int vflags =
|
|
Packit Service |
9f2c4a |
VERTO_EV_FLAG_PERSIST |
|
|
Packit Service |
9f2c4a |
VERTO_EV_FLAG_IO_READ |
|
|
Packit Service |
9f2c4a |
VERTO_EV_FLAG_IO_CLOSE_FD;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
char *opt_config_file = NULL;
|
|
Packit Service |
9f2c4a |
char *opt_config_dir = NULL;
|
|
Packit Service |
9f2c4a |
char *opt_config_socket = NULL;
|
|
Packit Service |
9f2c4a |
int opt_daemon = 0;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
struct gssproxy_ctx *gpctx;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
static struct gp_service *
|
|
Packit Service |
9f2c4a |
find_service_by_name(struct gp_config *cfg, const char *name)
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
int i;
|
|
Packit Service |
9f2c4a |
struct gp_service *ret = NULL;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
for (i = 0; i < cfg->num_svcs; i++) {
|
|
Packit Service |
9f2c4a |
if (strcmp(cfg->svcs[i]->name, name) == 0) {
|
|
Packit Service |
9f2c4a |
ret = cfg->svcs[i];
|
|
Packit Service |
9f2c4a |
break;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
return ret;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
static verto_ev *setup_socket(char *sock_name, verto_ctx *vctx)
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
struct gp_sock_ctx *sock_ctx;
|
|
Packit Service |
9f2c4a |
verto_ev *ev;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
sock_ctx = init_unix_socket(gpctx, sock_name);
|
|
Packit Service |
9f2c4a |
if (!sock_ctx) {
|
|
Packit Service |
9f2c4a |
return NULL;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ev = verto_add_io(vctx, vflags, accept_sock_conn, sock_ctx->fd);
|
|
Packit Service |
9f2c4a |
if (!ev) {
|
|
Packit Service |
9f2c4a |
return NULL;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
verto_set_private(ev, sock_ctx, free_unix_socket);
|
|
Packit Service |
9f2c4a |
return ev;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
static int init_sockets(verto_ctx *vctx, struct gp_config *old_config)
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
int i;
|
|
Packit Service |
9f2c4a |
struct gp_sock_ctx *sock_ctx;
|
|
Packit Service |
9f2c4a |
verto_ev *ev;
|
|
Packit Service |
9f2c4a |
struct gp_service *svc;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* init main socket */
|
|
Packit Service |
9f2c4a |
if (!old_config) {
|
|
Packit Service |
9f2c4a |
ev = setup_socket(gpctx->config->socket_name, vctx);
|
|
Packit Service |
9f2c4a |
if (!ev) {
|
|
Packit Service |
9f2c4a |
return 1;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
gpctx->sock_ev = ev;
|
|
Packit Service |
9f2c4a |
} else if (strcmp(old_config->socket_name,
|
|
Packit Service |
9f2c4a |
gpctx->config->socket_name) != 0) {
|
|
Packit Service |
9f2c4a |
ev = setup_socket(gpctx->config->socket_name, vctx);
|
|
Packit Service |
9f2c4a |
if (!ev) {
|
|
Packit Service |
9f2c4a |
return 1;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
gpctx->sock_ev = ev;
|
|
Packit Service |
9f2c4a |
verto_del(gpctx->sock_ev);
|
|
Packit Service |
9f2c4a |
} else {
|
|
Packit Service |
9f2c4a |
/* free_config will erase the socket name; update it accordingly */
|
|
Packit Service |
9f2c4a |
sock_ctx = verto_get_private(gpctx->sock_ev);
|
|
Packit Service |
9f2c4a |
sock_ctx->socket = gpctx->config->socket_name;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* propagate any sockets that shouldn't change */
|
|
Packit Service |
9f2c4a |
if (old_config) {
|
|
Packit Service |
9f2c4a |
for (i = 0; i < old_config->num_svcs; i++) {
|
|
Packit Service |
9f2c4a |
if (old_config->svcs[i]->ev) {
|
|
Packit Service |
9f2c4a |
svc = find_service_by_name(gpctx->config,
|
|
Packit Service |
9f2c4a |
old_config->svcs[i]->name);
|
|
Packit Service |
9f2c4a |
if (svc &&
|
|
Packit Service |
9f2c4a |
((svc->socket == old_config->svcs[i]->socket) ||
|
|
Packit Service |
9f2c4a |
((svc->socket != NULL) &&
|
|
Packit Service |
9f2c4a |
(old_config->svcs[i]->socket != NULL) &&
|
|
Packit Service |
9f2c4a |
strcmp(svc->socket,
|
|
Packit Service |
9f2c4a |
old_config->svcs[i]->socket) == 0))) {
|
|
Packit Service |
9f2c4a |
svc->ev = old_config->svcs[i]->ev;
|
|
Packit Service |
9f2c4a |
sock_ctx = verto_get_private(svc->ev);
|
|
Packit Service |
9f2c4a |
sock_ctx->socket = svc->socket;
|
|
Packit Service |
9f2c4a |
} else {
|
|
Packit Service |
9f2c4a |
verto_del(old_config->svcs[i]->ev);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* init all other sockets */
|
|
Packit Service |
9f2c4a |
for (i = 0; i < gpctx->config->num_svcs; i++) {
|
|
Packit Service |
9f2c4a |
svc = gpctx->config->svcs[i];
|
|
Packit Service |
9f2c4a |
if (svc->socket != NULL && svc->ev == NULL) {
|
|
Packit Service |
9f2c4a |
ev = setup_socket(svc->socket, vctx);
|
|
Packit Service |
9f2c4a |
if (!ev) {
|
|
Packit Service |
9f2c4a |
return 1;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
svc->ev = ev;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
return 0;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
static void hup_handler(verto_ctx *vctx, verto_ev *ev UNUSED)
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
int ret;
|
|
Packit Service |
9f2c4a |
struct gp_config *new_config, *old_config;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
GPDEBUG("Received SIGHUP; re-reading config.\n");
|
|
Packit Service |
9f2c4a |
new_config = read_config(opt_config_file, opt_config_dir,
|
|
Packit Service |
9f2c4a |
opt_config_socket, opt_daemon);
|
|
Packit Service |
9f2c4a |
if (!new_config) {
|
|
Packit Service |
9f2c4a |
GPERROR("Error reading new configuration on SIGHUP; keeping old "
|
|
Packit Service |
9f2c4a |
"configuration instead!\n");
|
|
Packit Service |
9f2c4a |
return;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
old_config = gpctx->config;
|
|
Packit Service |
9f2c4a |
gpctx->config = new_config;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ret = init_sockets(vctx, old_config);
|
|
Packit Service |
9f2c4a |
if (ret != 0) {
|
|
Packit Service |
9f2c4a |
exit(ret);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* conditionally reload kernel interface */
|
|
Packit Service |
9f2c4a |
init_proc_nfsd(gpctx->config);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
free_config(&old_config);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
GPDEBUG("New config loaded successfully.\n");
|
|
Packit Service |
9f2c4a |
return;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
int main(int argc, const char *argv[])
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
int opt;
|
|
Packit Service |
9f2c4a |
poptContext pc;
|
|
Packit Service |
9f2c4a |
int opt_interactive = 0;
|
|
Packit Service |
9f2c4a |
int opt_version = 0;
|
|
Packit Service |
9f2c4a |
int opt_debug = 0;
|
|
Packit Service |
9f2c4a |
int opt_debug_level = 0;
|
|
Packit Service |
9f2c4a |
verto_ctx *vctx;
|
|
Packit Service |
9f2c4a |
verto_ev *ev;
|
|
Packit Service |
9f2c4a |
int wait_fd;
|
|
Packit Service |
9f2c4a |
int ret = -1;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* initialize debug client id to 0 in the main thread */
|
|
Packit Service |
9f2c4a |
/* we do this early, before any code starts using debug statements */
|
|
Packit Service |
9f2c4a |
gp_debug_set_conn_id(0);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
struct poptOption long_options[] = {
|
|
Packit Service |
9f2c4a |
POPT_AUTOHELP
|
|
Packit Service |
9f2c4a |
{"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \
|
|
Packit Service |
9f2c4a |
_("Become a daemon (default)"), NULL }, \
|
|
Packit Service |
9f2c4a |
{"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \
|
|
Packit Service |
9f2c4a |
_("Run interactive (not a daemon)"), NULL}, \
|
|
Packit Service |
9f2c4a |
{"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \
|
|
Packit Service |
9f2c4a |
_("Specify a non-default config file"), NULL}, \
|
|
Packit Service |
9f2c4a |
{"configdir", 'C', POPT_ARG_STRING, &opt_config_dir, 0, \
|
|
Packit Service |
9f2c4a |
_("Specify a non-default config directory"), NULL}, \
|
|
Packit Service |
9f2c4a |
{"socket", 's', POPT_ARG_STRING, &opt_config_socket, 0, \
|
|
Packit Service |
9f2c4a |
_("Specify a custom default socket"), NULL}, \
|
|
Packit Service |
9f2c4a |
{"debug", 'd', POPT_ARG_NONE, &opt_debug, 0, \
|
|
Packit Service |
9f2c4a |
_("Enable debugging"), NULL}, \
|
|
Packit Service |
9f2c4a |
{"debug-level", '\0', POPT_ARG_INT, &opt_debug_level, 0, \
|
|
Packit Service |
9f2c4a |
_("Set debugging level"), NULL}, \
|
|
Packit Service |
9f2c4a |
{"version", '\0', POPT_ARG_NONE, &opt_version, 0, \
|
|
Packit Service |
9f2c4a |
_("Print version number and exit"), NULL }, \
|
|
Packit Service |
9f2c4a |
POPT_TABLEEND
|
|
Packit Service |
9f2c4a |
};
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
pc = poptGetContext(argv[0], argc, argv, long_options, 0);
|
|
Packit Service |
9f2c4a |
while((opt = poptGetNextOpt(pc)) != -1) {
|
|
Packit Service |
9f2c4a |
switch(opt) {
|
|
Packit Service |
9f2c4a |
default:
|
|
Packit Service |
9f2c4a |
fprintf(stderr, "\nInvalid option %s: %s\n\n",
|
|
Packit Service |
9f2c4a |
poptBadOption(pc, 0), poptStrerror(opt));
|
|
Packit Service |
9f2c4a |
poptPrintUsage(pc, stderr, 0);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ret = 1;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (opt_version) {
|
|
Packit Service |
9f2c4a |
puts(VERSION""DISTRO_VERSION""PRERELEASE_VERSION);
|
|
Packit Service |
9f2c4a |
ret = 0;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (opt_debug || opt_debug_level > 0) {
|
|
Packit Service |
9f2c4a |
if (opt_debug_level == 0) opt_debug_level = 1;
|
|
rpm-build |
cc42d0 |
gp_debug_toggle(opt_debug_level);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (opt_daemon && opt_interactive) {
|
|
Packit Service |
9f2c4a |
fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n");
|
|
Packit Service |
9f2c4a |
poptPrintUsage(pc, stderr, 0);
|
|
Packit Service |
9f2c4a |
ret = 0;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (opt_interactive) {
|
|
Packit Service |
9f2c4a |
opt_daemon = 2;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
gpctx = calloc(1, sizeof(struct gssproxy_ctx));
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
gpctx->config = read_config(opt_config_file,
|
|
Packit Service |
9f2c4a |
opt_config_dir,
|
|
Packit Service |
9f2c4a |
opt_config_socket,
|
|
Packit Service |
9f2c4a |
opt_daemon);
|
|
Packit Service |
9f2c4a |
if (!gpctx->config) {
|
|
Packit Service |
9f2c4a |
ret = EXIT_FAILURE;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
init_server(gpctx->config->daemonize, &wait_fd);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
write_pid();
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
vctx = init_event_loop();
|
|
Packit Service |
9f2c4a |
if (!vctx) {
|
|
Packit Service |
9f2c4a |
fprintf(stderr, "Failed to initialize event loop. "
|
|
Packit Service |
9f2c4a |
"Is there at least one libverto backend installed?\n");
|
|
Packit Service |
9f2c4a |
ret = 1;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
gpctx->vctx = vctx;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* Add SIGHUP here so that gpctx is in scope for the handler */
|
|
Packit Service |
9f2c4a |
ev = verto_add_signal(vctx, VERTO_EV_FLAG_PERSIST, hup_handler, SIGHUP);
|
|
Packit Service |
9f2c4a |
if (!ev) {
|
|
Packit Service |
9f2c4a |
fprintf(stderr, "Failed to register SIGHUP handler with verto!\n");
|
|
Packit Service |
9f2c4a |
ret = 1;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ret = init_sockets(vctx, NULL);
|
|
Packit Service |
9f2c4a |
if (ret != 0) {
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* We need to tell nfsd that GSS-Proxy is available before it starts,
|
|
Packit Service |
9f2c4a |
* as nfsd needs to know GSS-Proxy is in use before the first time it
|
|
Packit Service |
9f2c4a |
* needs to call accept_sec_context. */
|
|
Packit Service |
9f2c4a |
init_proc_nfsd(gpctx->config);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* Now it is safe to tell the init system that we're done starting up,
|
|
Packit Service |
9f2c4a |
* so it can continue with dependencies and start nfsd */
|
|
Packit Service |
9f2c4a |
init_done(wait_fd);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ret = drop_privs(gpctx->config);
|
|
Packit Service |
9f2c4a |
if (ret) {
|
|
Packit Service |
9f2c4a |
ret = EXIT_FAILURE;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ret = gp_workers_init(gpctx);
|
|
Packit Service |
9f2c4a |
if (ret) {
|
|
Packit Service |
9f2c4a |
ret = EXIT_FAILURE;
|
|
Packit Service |
9f2c4a |
goto cleanup;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
verto_run(vctx);
|
|
Packit Service |
9f2c4a |
verto_free(vctx);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
gp_workers_free(gpctx->workers);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
fini_server();
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
free_config(&gpctx->config);
|
|
Packit Service |
9f2c4a |
free(gpctx);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
ret = 0;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
cleanup:
|
|
Packit Service |
9f2c4a |
poptFreeContext(pc);
|
|
Packit Service |
9f2c4a |
free(opt_config_file);
|
|
Packit Service |
9f2c4a |
free(opt_config_dir);
|
|
Packit Service |
9f2c4a |
free(opt_config_socket);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
#ifdef HAVE_VERTO_CLEANUP
|
|
Packit Service |
9f2c4a |
verto_cleanup();
|
|
Packit Service |
9f2c4a |
#endif
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
return ret;
|
|
Packit Service |
9f2c4a |
}
|