diff options
author | Sergey Poznyakoff <gray@nxc.no> | 2013-11-14 22:11:02 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@nxc.no> | 2013-11-14 22:30:39 +0200 |
commit | a966a5217551865c18b1018da179d0e5655bdf7a (patch) | |
tree | 2907f199532f3cdc2054ec18aa61cd49b8f85efb | |
parent | ce172b98e2f80888d5701da45ddd73b4512df6e2 (diff) | |
download | jumper-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.8in | 54 | ||||
-rw-r--r-- | src/config.c | 34 | ||||
-rw-r--r-- | src/cons_ip.c | 27 | ||||
-rw-r--r-- | src/environ.c | 3 | ||||
-rw-r--r-- | src/jumper.c | 2 | ||||
-rw-r--r-- | src/jumper.h | 25 | ||||
-rw-r--r-- | src/listener.c | 123 |
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; |