aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@nxc.no>2013-11-14 22:11:02 +0200
committerSergey Poznyakoff <gray@nxc.no>2013-11-14 22:30:39 +0200
commita966a5217551865c18b1018da179d0e5655bdf7a (patch)
tree2907f199532f3cdc2054ec18aa61cd49b8f85efb
parentce172b98e2f80888d5701da45ddd73b4512df6e2 (diff)
downloadjumper-a966a5217551865c18b1018da179d0e5655bdf7a.tar.gz
jumper-a966a5217551865c18b1018da179d0e5655bdf7a.tar.bz2
Add startup and cleanup global actions.
* src/config.c (cb_onexit): Rename to cb_onevent. Add new event codes. (listen_kw) <onexit>: Rename to onevent. * src/cons_ip.c (ip_handler): Use listener_kve_init to set up kve. * src/environ.c (defenv) <JUMPER_ACTION>: New variable. * src/jumper.c (main): Call startup and cleanup actions. * src/jumper.h (action_type): New enum. (onexit_action) <onsig>: Remove. <type>: New member. (listener_kve_init) (listener_run_action): New functions. * src/listener.c (listener_kve_init): New function. (listener_run_action): New function. (listener_run): Rewrite. * doc/jumper.8in: Document changes.
-rw-r--r--doc/jumper.8in54
-rw-r--r--src/config.c34
-rw-r--r--src/cons_ip.c27
-rw-r--r--src/environ.c3
-rw-r--r--src/jumper.c2
-rw-r--r--src/jumper.h25
-rw-r--r--src/listener.c123
7 files changed, 187 insertions, 81 deletions
diff --git a/doc/jumper.8in b/doc/jumper.8in
index 470feaa..daef561 100644
--- a/doc/jumper.8in
+++ b/doc/jumper.8in
@@ -458,6 +458,14 @@ Program version
.B JUMPER_LOCUS
Location in the configuration file which caused execution of the
command (file name and line number separated with a colon).
+.TP
+.B JUMPER_ACTION
+Action code; one of:
+.BR startup ,
+.BR cleanup ,
+.BR onexit ,
+or
+.BR onsignal .
.RE
.IP
The \fBenviron\fR statement allows for trimming the environment. Its
@@ -523,14 +531,34 @@ The \fIVALUE\fR can contain macro variables, which will be expanded prior
to the assignment.
.RE
.TP
-\fBonexit\fR \fICODE\fR \fB{ ... };\fR
+\fBonevent\fR \fIEV\fR \fB{ ... };\fR
This block statement instructs \fBjumper\fR to perform a specified
-action whenever the handler command terminates with the given
-\fICODE\fR. Allowed values for the latter are: decimal numbers in the
-range \fB0..127\fR, \fBSIG+\fR followed by a decimal number, in which
-case the statement will be executed if the command terminates on the
-given signal, or any of the symbolic signal names defined in
-.BR signal.h .
+action when the event \fIEV\fR is detected. The valid events are:
+.RS +10
+.TP
+.B STARTUP
+The action is run immediately after
+.B jumper
+starts up, before it begins listening on interfaces. It can be used
+to set up firewall rules, etc.
+.TP
+.B CLEANUP
+The action is run before
+.B jumper
+terminates, after termination of all commands.
+.TP
+Decimal number in range \fB0..127\fR
+The action is performed when the command terminates with the given
+code.
+.TP
+.BI SIG+ N
+The action is performed when the command
+terminates on signal \fIN\fR (decimal number)
+.TP
+Symbolic signal name as defined in \fBsignal.h\fR
+The action is performed when the command
+terminates on this signal.
+.RE
The following statements can be used within the block:
@@ -550,6 +578,14 @@ located.
.B line
Line number in that file.
.TP
+.B action
+Action code; one of:
+.BR startup ,
+.BR cleanup ,
+.BR onexit ,
+or
+.BR onsignal .
+.TP
.B status
Program termination status as returned by the
.BR waitpid (2)
@@ -678,7 +714,7 @@ modify the handling of \fBreason=disconnect\fR in the
.B /etc/vpnc/vpnc-script
file.
.PP
-Notice also, that you might have to specify additional \fBonexit\fR
+Notice also, that you might have to specify additional \fBonevent\fR
rules to clean-up the firewall table in case of the hang-up or similar
conditions. For example,
.BR vpnc (8)
@@ -690,7 +726,7 @@ with code 1. If you modify the script so that it handles
to the \fBlisten\fR statement:
.PP
.EX
-onexit 1 {
+onevent 1 {
command "/etc/vpnc/vpnc-script";
environ "reason=cleanup";
}
diff --git a/src/config.c b/src/config.c
index b2937fb..8707598 100644
--- a/src/config.c
+++ b/src/config.c
@@ -453,11 +453,11 @@ static struct transtab sig_trans[] = {
#undef S
static int
-cb_onexit(enum grecs_callback_command cmd, grecs_node_t *node,
+cb_onevent(enum grecs_callback_command cmd, grecs_node_t *node,
void *varptr, void *cb_data)
{
listener_t *lp = varptr;
- onexit_action_t *act, **pact = cb_data;
+ action_t *act, **pact = cb_data;
char *arg, *p;
unsigned long n;
@@ -471,9 +471,9 @@ cb_onexit(enum grecs_callback_command cmd, grecs_node_t *node,
act->timeout = 5;
arg = node->v.value->v.string;
if (trans_strtotok(ex_trans, arg, &act->code) == 0) {
- act->onsig = 0;
+ act->type = action_onexit;
} else if (trans_strtotok(sig_trans, arg, &act->code) == 0) {
- act->onsig = 1;
+ act->type = action_onsignal;
} else if (strncmp(arg, "SIG+", 4) == 0) {
act->code = strtoul(arg+4, &p, 10);
if (*p) {
@@ -482,7 +482,11 @@ cb_onexit(enum grecs_callback_command cmd, grecs_node_t *node,
free(act);
return 1;
}
- act->onsig = 1;
+ act->type = action_onsignal;
+ } else if (strcmp(arg, "STARTUP") == 0) {
+ act->type = action_startup;
+ } else if (strcmp(arg, "CLEANUP") == 0) {
+ act->type = action_cleanup;
} else if (isdigit(arg[0])) {
errno = 0;
n = strtoul(arg, &p, 10);
@@ -493,7 +497,7 @@ cb_onexit(enum grecs_callback_command cmd, grecs_node_t *node,
return 1;
}
act->code = n;
- act->onsig = 0;
+ act->type = action_onexit;
} else {
grecs_error(&node->locus, 0,
"not an exit code or signal number");
@@ -521,24 +525,23 @@ cb_onexit(enum grecs_callback_command cmd, grecs_node_t *node,
return 0;
}
-static struct grecs_keyword onexit_kw[] = {
+static struct grecs_keyword onevent_kw[] = {
{ "command", NULL, "run this command",
grecs_type_string, GRECS_DFLT, NULL,
- offsetof(onexit_action_t,command) },
+ offsetof(action_t,command) },
{ "option", NULL, "List of additional options",
grecs_type_string, GRECS_LIST, NULL,
- offsetof(onexit_action_t,options),
+ offsetof(action_t,options),
cb_option },
{ "environ", "<arg: string> <arg: string>...", "Modify environment",
grecs_type_string, GRECS_DFLT, NULL,
- offsetof(onexit_action_t,env),
+ offsetof(action_t,env),
cb_environ },
{ "timeout", "seconds", "command execution timeout",
grecs_type_uint, GRECS_DFLT, NULL,
- offsetof(onexit_action_t,timeout) },
+ offsetof(action_t,timeout) },
{ NULL }
};
-
static struct grecs_keyword listen_kw[] = {
{ "match-source", NULL, "match packets coming from these IP addresses",
@@ -558,10 +561,11 @@ static struct grecs_keyword listen_kw[] = {
grecs_type_string, GRECS_DFLT, NULL,
offsetof(listener_t,env),
cb_environ },
- { "onexit", "<code: string>",
- "Run <action> if command exits with <code>",
+ { "onevent", "code: string",
+ "Run specified action on the given event",
grecs_type_section, GRECS_DFLT, NULL, 0,
- cb_onexit, NULL, onexit_kw },
+ cb_onevent, NULL, onevent_kw },
+
{ NULL }
};
diff --git a/src/cons_ip.c b/src/cons_ip.c
index 89633ab..b5db492 100644
--- a/src/cons_ip.c
+++ b/src/cons_ip.c
@@ -21,8 +21,7 @@ void
ip_handler(struct ip *ip, unsigned int length)
{
char ipbuf[16][2];
- char linebuf[64];
- char *kve[11];
+ char *kve[KVE_MINSIZE+6];
int i;
listener_t *lp;
@@ -68,24 +67,12 @@ ip_handler(struct ip *ip, unsigned int length)
lp->prog);
}
- i = 0;
- kve[i++] = "program";
- kve[i++] = (char*)program_name;
-
- kve[i++] = "file";
- kve[i++] = lp->locus.beg.file;
-
- kve[i++] = "line";
- snprintf(linebuf, sizeof(linebuf), "%u", lp->locus.beg.line);
- kve[i++] = linebuf;
-
- kve[i++] = "src";
- kve[i++] = ipbuf[0];
-
- kve[i++] = "dst";
- kve[i++] = ipbuf[0];
-
- kve[i] = NULL;
+ listener_kve_init(kve, sizeof(kve)/sizeof(kve[0]),
+ lp,
+ "action", "listener",
+ "src", ipbuf[0],
+ "dst", ipbuf[1],
+ NULL);
listener_start(lp, kve);
}
diff --git a/src/environ.c b/src/environ.c
index 17681c6..934da75 100644
--- a/src/environ.c
+++ b/src/environ.c
@@ -101,7 +101,8 @@ static char *defenv[] = {
"JUMPER=${program}",
"JUMPER_VERSION=" PACKAGE_VERSION,
"JUMPER_LOCUS=${file}:${line}",
- NULL
+ "JUMPER_ACTION=${action}",
+ NULL,
};
char **
diff --git a/src/jumper.c b/src/jumper.c
index 6601b71..8da116b 100644
--- a/src/jumper.c
+++ b/src/jumper.c
@@ -190,11 +190,13 @@ main(int argc, char **argv)
storepid(pidfile);
signal_setup(sigmain);
+ listener_run_action(action_startup);
while (!stop)
listener_run();
progman_terminate();
+ listener_run_action(action_cleanup);
diag(LOG_INFO, "%s %s stopped", program_name, VERSION);
diff --git a/src/jumper.h b/src/jumper.h
index e19ff35..0edabf3 100644
--- a/src/jumper.h
+++ b/src/jumper.h
@@ -88,16 +88,23 @@ typedef struct ipv4_match_list { /* IPv4 address match list */
ipv4_cidr_t cidr; /* CIDR */
} ipv4_match_list_t;
-typedef struct onexit_action {
- struct onexit_action *next;
+enum action_type {
+ action_startup,
+ action_cleanup,
+ action_onexit,
+ action_onsignal
+};
+
+typedef struct action {
+ struct action *next;
int code;
- int onsig;
+ enum action_type type;
char *command;
char **env;
int options;
unsigned timeout;
struct grecs_locus locus;
-} onexit_action_t;
+} action_t;
enum listener_status {
stat_down,
@@ -117,7 +124,8 @@ typedef struct listener { /* Listener */
char *prog; /* Command to bring link up */
char **env; /* Environment */
int options; /* Execution options */
- onexit_action_t *act_head, *act_tail;
+ action_t *act_head, *act_tail;
+
struct grecs_locus locus; /* Location in the config file */
pid_t pid; /* PID of the prog, if running,
0 otherwise */
@@ -147,6 +155,13 @@ void listener_kill_redirector(listener_t *lp, int what);
void listener_start(listener_t *lp, char **kve);
void onexit_reaction(listener_t *lp);
+#define KVE_MINSIZE 7
+
+void listener_kve_init(char **kve, int kvn, listener_t *lp, ...);
+int listener_run_action(int a);
+
+
+
#define EX_OK 0
struct ip;
diff --git a/src/listener.c b/src/listener.c
index c781966..087c694 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -210,6 +210,80 @@ listener_init()
grecs_line_acc_free();
}
+
+void
+listener_kve_init(char **kve, int kvn, listener_t *lp, ...)
+{
+ int i = 0;
+ static char linebuf[64];
+ va_list ap;
+ char *p;
+
+ if (kvn < KVE_MINSIZE) {
+ diag(LOG_CRIT, "%s:%d: INTERNAL ERROR", __FILE__, __LINE__);
+ abort();
+ }
+
+ kve[i++] = "program";
+ kve[i++] = (char*)program_name;
+
+ kve[i++] = "file";
+ kve[i++] = lp->locus.beg.file;
+
+ kve[i++] = "line";
+ snprintf(linebuf, sizeof(linebuf), "%u", lp->locus.beg.line);
+ kve[i++] = linebuf;
+
+ va_start(ap, lp);
+ while ((p = va_arg(ap,char*))) {
+ if (i == kvn) {
+ diag(LOG_CRIT, "%s:%d: INTERNAL ERROR",
+ __FILE__, __LINE__);
+ abort();
+ }
+ kve[i++] = p;
+ }
+ va_end(ap);
+ kve[i] = NULL;
+}
+
+static char *action_str[] = {
+ "startup",
+ "cleanup",
+ "onexit",
+ "onsignal"
+};
+
+int
+listener_run_action(int a)
+{
+ listener_t *lp;
+ char *kve[KVE_MINSIZE+2];
+ int err;
+
+ for (lp = l_head; lp; lp = lp->next) {
+ action_t *act;
+
+ listener_kve_init(kve, sizeof(kve)/sizeof(kve[0]),
+ lp,
+ "action", action_str[a],
+ NULL);
+
+ for (act = lp->act_head; act; act = act->next) {
+ if (act->type == a &&
+ progman_start(type_action, lp,
+ &act->locus,
+ act->options,
+ act->timeout,
+ act->command,
+ act->env, kve))
+ err++;
+ }
+ }
+ return err;
+}
+
+
void
listener_run()
{
@@ -324,33 +398,20 @@ listener_print_status(listener_t *lp)
}
static void
-runaction(listener_t *lp, onexit_action_t *act)
+runaction(listener_t *lp, action_t *act)
{
- int i = 0;
- char *kve[11];
- char linebuf[64];
+ char *kve[KVE_MINSIZE + 6];
char codebuf[64];
char statbuf[64];
-
- kve[i++] = "program";
- kve[i++] = (char*)program_name;
-
- kve[i++] = "file";
- kve[i++] = lp->locus.beg.file;
- kve[i++] = "line";
- snprintf(linebuf, sizeof(linebuf), "%u", lp->locus.beg.line);
- kve[i++] = linebuf;
-
- kve[i++] = "status";
snprintf(statbuf, sizeof(statbuf), "%u", lp->progstat);
- kve[i++] = statbuf;
-
snprintf(codebuf, sizeof(codebuf), "%u", act->code);
- kve[i++] = "exitcode";
- kve[i++] = codebuf;
-
- kve[i] = NULL;
+ listener_kve_init(kve, sizeof(kve)/sizeof(kve[0]),
+ lp,
+ "action", action_str[act->type],
+ "status", statbuf,
+ "exitcode", codebuf,
+ NULL);
if (progman_start(type_action, lp, &act->locus, act->options,
act->timeout, act->command, act->env, kve))
@@ -362,22 +423,22 @@ runaction(listener_t *lp, onexit_action_t *act)
void
onexit_reaction(listener_t *lp)
{
- onexit_action_t *act;
+ action_t *act;
int code;
-
+ enum action_type type;
+
lp->status = stat_onexit;
if (WIFEXITED(lp->progstat)) {
+ type = action_onexit;
code = WEXITSTATUS(lp->progstat);
- for (act = lp->act_head; act; act = act->next) {
- if (!act->onsig && act->code == code)
- runaction(lp, act);
- }
} else if (WIFSIGNALED(lp->progstat)) {
+ type = action_onsignal;
code = WTERMSIG(lp->progstat);
- for (act = lp->act_head; act; act = act->next) {
- if (act->onsig && act->code == code)
- runaction(lp, act);
- }
+ }
+
+ for (act = lp->act_head; act; act = act->next) {
+ if (act->type == type && act->code == code)
+ runaction(lp, act);
}
if (lp->act_count == 0)
lp->status = stat_down;

Return to:

Send suggestions and report system problems to the System administrator.