charon-cmd: add a connection object and its initiation to charon-cmd

This commit is contained in:
Martin Willi 2013-03-26 15:07:15 +01:00
parent be44723de0
commit 78d7a0f7e2
6 changed files with 313 additions and 10 deletions

View File

@ -2,6 +2,7 @@ sbin_PROGRAMS = charon-cmd
charon_cmd_SOURCES = \
cmd/cmd_options.h cmd/cmd_options.c \
cmd/cmd_connection.h cmd/cmd_connection.c \
charon-cmd.c
charon-cmd.o : $(top_builddir)/config.status

View File

@ -33,12 +33,18 @@
#include <threading/thread.h>
#include "cmd/cmd_options.h"
#include "cmd/cmd_connection.h"
/**
* Loglevel configuration
*/
static level_t levels[DBG_MAX];
/**
* Connection to initiate
*/
static cmd_connection_t *conn;
/**
* hook in library for debugging messages
*/
@ -61,18 +67,27 @@ static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
}
}
/**
* Clean up connection definition atexit()
*/
static void cleanup_conn()
{
DESTROY_IF(conn);
}
/**
* Run the daemon and handle unix signals
*/
static void run()
static int run()
{
sigset_t set;
/* handle SIGINT, SIGHUP ans SIGTERM in this handler */
/* handle SIGINT, SIGHUP and SIGTERM in this handler */
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGHUP);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
while (TRUE)
@ -84,7 +99,7 @@ static void run()
if (error)
{
DBG1(DBG_DMN, "error %d while waiting for a signal", error);
return;
return 1;
}
switch (sig)
{
@ -107,13 +122,18 @@ static void run()
{
DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
return;
return 0;
}
case SIGTERM:
{
DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
return;
return 0;
}
case SIGUSR1:
{ /* an error occured */
charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
return 1;
}
default:
{
@ -212,7 +232,7 @@ static void handle_arguments(int argc, char *argv[])
while (TRUE)
{
struct option long_opts[CMD_OPT_COUNT + 1] = {};
int i;
int i, opt;
for (i = 0; i < CMD_OPT_COUNT; i++)
{
@ -221,7 +241,8 @@ static void handle_arguments(int argc, char *argv[])
long_opts[i].has_arg = cmd_options[i].has_arg;
}
switch (getopt_long(argc, argv, "", long_opts, NULL))
opt = getopt_long(argc, argv, "", long_opts, NULL);
switch (opt)
{
case EOF:
break;
@ -232,6 +253,10 @@ static void handle_arguments(int argc, char *argv[])
printf("%s, strongSwan %s\n", "charon-cmd", VERSION);
exit(0);
default:
if (conn->handle(conn, opt, optarg))
{
continue;
}
usage(stderr, NULL, argv[0]);
exit(1);
}
@ -275,6 +300,8 @@ int main(int argc, char *argv[])
{
levels[group] = LEVEL_CTRL;
}
conn = cmd_connection_create();
atexit(cleanup_conn);
handle_arguments(argc, argv);
@ -320,7 +347,5 @@ int main(int argc, char *argv[])
/* start daemon with thread-pool */
charon->start(charon);
/* wait for signal */
run();
return 0;
return run();
}

View File

@ -0,0 +1,216 @@
/*
* Copyright (C) 2013 Martin Willi
* Copyright (C) 2013 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "cmd_connection.h"
#include <signal.h>
#include <unistd.h>
#include <utils/debug.h>
#include <processing/jobs/callback_job.h>
#include <daemon.h>
typedef struct private_cmd_connection_t private_cmd_connection_t;
/**
* Private data of an cmd_connection_t object.
*/
struct private_cmd_connection_t {
/**
* Public cmd_connection_t interface.
*/
cmd_connection_t public;
/**
* Process ID to terminate on failure
*/
pid_t pid;
/**
* Hostname to connect to
*/
char *host;
/**
* Local identity
*/
char *identity;
};
/**
* Shut down application
*/
static void terminate(private_cmd_connection_t *this)
{
kill(this->pid, SIGUSR1);
}
/**
* Create peer config with associated ike config
*/
static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
{
ike_cfg_t *ike_cfg;
peer_cfg_t *peer_cfg;
ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE,
charon->socket->get_port(charon->socket, FALSE),
this->host, FALSE, IKEV2_UDP_PORT,
FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("cmd", ike_cfg,
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
36000, 0, /* rekey 10h, reauth none */
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
30, 0, /* DPD delay, timeout */
FALSE, NULL, NULL); /* mediation */
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
return peer_cfg;
}
/**
* Attach authentication configs to peer config
*/
static void add_auth_cfgs(private_cmd_connection_t *this, peer_cfg_t *peer_cfg)
{
auth_cfg_t *auth;
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
auth->add(auth, AUTH_RULE_IDENTITY,
identification_create_from_string(this->identity));
peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_IDENTITY,
identification_create_from_string(this->host));
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
}
/**
* Attach child config to peer config
*/
static child_cfg_t* create_child_cfg(private_cmd_connection_t *this)
{
child_cfg_t *child_cfg;
traffic_selector_t *ts;
lifetime_cfg_t lifetime = {
.time = {
.life = 10800 /* 3h */,
.rekey = 10200 /* 2h50min */,
.jitter = 300 /* 5min */
}
};
child_cfg = child_cfg_create("cmd", &lifetime,
NULL, FALSE, MODE_TUNNEL, /* updown, hostaccess */
ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
0, 0, NULL, NULL, 0);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
"0.0.0.0", 0, "255.255.255.255", 65535);
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
return child_cfg;
}
/**
* Initiate the configured connection
*/
static job_requeue_t initiate(private_cmd_connection_t *this)
{
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
if (!this->host)
{
DBG1(DBG_CFG, "unable to initiate, missing --host option");
terminate(this);
return JOB_REQUEUE_NONE;
}
if (!this->identity)
{
DBG1(DBG_CFG, "unable to initiate, missing --identity option");
terminate(this);
return JOB_REQUEUE_NONE;
}
peer_cfg = create_peer_cfg(this);
add_auth_cfgs(this, peer_cfg);
child_cfg = create_child_cfg(this);
peer_cfg->add_child_cfg(peer_cfg, child_cfg->get_ref(child_cfg));
if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
controller_cb_empty, NULL, 0) != SUCCESS)
{
terminate(this);
}
return JOB_REQUEUE_NONE;
}
METHOD(cmd_connection_t, handle, bool,
private_cmd_connection_t *this, cmd_option_type_t opt, char *arg)
{
switch (opt)
{
case CMD_OPT_HOST:
this->host = arg;
break;
case CMD_OPT_IDENTITY:
this->identity = arg;
break;
default:
return FALSE;
}
return TRUE;
}
METHOD(cmd_connection_t, destroy, void,
private_cmd_connection_t *this)
{
free(this);
}
/**
* See header
*/
cmd_connection_t *cmd_connection_create()
{
private_cmd_connection_t *this;
INIT(this,
.public = {
.handle = _handle,
.destroy = _destroy,
},
.pid = getpid(),
);
/* queue job, gets initiated as soon as we are up and running */
lib->processor->queue_job(lib->processor,
(job_t*)callback_job_create_with_prio(
(callback_job_cb_t)initiate, this, NULL,
(callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2013 Martin Willi
* Copyright (C) 2013 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup cmd_connection cmd_connection
* @{ @ingroup cmd
*/
#ifndef CMD_CONNECTION_H_
#define CMD_CONNECTION_H_
#include <library.h>
#include "cmd_options.h"
typedef struct cmd_connection_t cmd_connection_t;
/**
* Connection definition to construct and initiate.
*/
struct cmd_connection_t {
/**
* Handle a command line option.
*
* @param opt option to handle
* @param arg option argument
* @return TRUE if option handled
*/
bool (*handle)(cmd_connection_t *this, cmd_option_type_t opt, char *arg);
/**
* Destroy a cmd_connection_t.
*/
void (*destroy)(cmd_connection_t *this);
};
/**
* Create a cmd_connection instance.
*/
cmd_connection_t *cmd_connection_create();
#endif /** CMD_CONNECTION_H_ @}*/

View File

@ -25,4 +25,8 @@ cmd_option_t cmd_options[CMD_OPT_COUNT] = {
"print this usage information and exit" },
{ CMD_OPT_VERSION, "version", no_argument, "",
"show version information and exit" },
{ CMD_OPT_HOST, "host", required_argument, "hostname",
"DNS name or address to connect to" },
{ CMD_OPT_IDENTITY, "identity", required_argument, "identity",
"identity the client uses for the IKE exchange" },
};

View File

@ -30,6 +30,8 @@ typedef enum cmd_option_type_t cmd_option_type_t;
enum cmd_option_type_t {
CMD_OPT_HELP,
CMD_OPT_VERSION,
CMD_OPT_HOST,
CMD_OPT_IDENTITY,
CMD_OPT_COUNT
};