aboutsummaryrefslogtreecommitdiff
path: root/src/jumper.h
blob: 448e8efff38339d149feb996b891004b616b3aba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* This file is part of Jumper
   Copyright (C) 2013, 2017, 2020 Sergey Poznyakoff
  
   Jumper 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 3, or (at your option)
   any later version.
  
   Jumper 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.
  
   You should have received a copy of the GNU General Public License
   along with Jumper.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <syslog.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define __EXPORTED_HEADERS__
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <sysexits.h>
#include <ctype.h>
#include <pcap.h>
#include "grecs.h"
#include "wordsplit.h"

#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
#  define __attribute__(x)
#endif

#define J_PRINTFLIKE(fmt,narg) __attribute__ ((__format__ (__printf__, fmt, narg)))

#ifndef SYSCONFDIR
# define SYSCONFDIR "/etc"
#endif
#ifndef LOCALSTATEDIR
# define LOCALSTATEDIR "/var"
#endif

#ifndef DEFAULT_CONFFILE
# define DEFAULT_CONFFILE SYSCONFDIR "/jumper.conf"
#endif

#ifndef DEFAULT_PIDFILE
# define DEFAULT_PIDFILE LOCALSTATEDIR "/run/jumper.pid"
#endif

#ifndef DEFAULT_HEARTBEAT
# define DEFAULT_HEARTBEAT 60
#endif

struct jumper_config {
	int foreground;
	char *pidfile;
	int debug_level;
	unsigned shutdown_timeout;
	unsigned heartbeat;
	/* logging settings */
	int facility;
	char *tag;
	int print_priority;
};

extern const char *program_name;
extern int log_to_stderr;

extern struct jumper_config config;

void *emalloc(size_t size);
void *ecalloc(size_t nmemb, size_t size);
void *erealloc(void *ptr, size_t size);
char *estrdup(const char *str);

void set_program_name(const char *arg);
void diag(int prio, const char *fmt, ...) J_PRINTFLIKE(2,3);
void debugprt(const char *fmt, ...) J_PRINTFLIKE(1,2);

#define debug(l, c) do { if (config.debug_level>=(l)) debugprt c; } while(0)

void jumper_print_grecs_diag(grecs_locus_t const *locus, int err, int errcode,
			     const char *msg);


struct transtab {
	char *name;
	int tok;
};

int trans_strtotok(struct transtab *tab, const char *str, int *ret);
char *trans_toktostr(struct transtab *tab, int tok);
char *trans_toknext(struct transtab *tab, int tok, int *next);
char *trans_tokfirst(struct transtab *tab, int tok, int *next);

void storepid(const char *pidfile);
void signal_setup(void (*sf) (int));

int get_priority(const char *arg, int *retval);
void config_help(void);
void config_init(void);
void config_preparse(void);
int config_finish(struct grecs_node *tree, int reconf);


typedef struct ipv4_cidr {               /* IPv4 CIDR */
	uint32_t addr;                   /* Network address */
	uint32_t netmask;                /* Netmask */
} ipv4_cidr_t;

typedef struct ipv4_match_list {         /* IPv4 address match list */
	struct ipv4_match_list *next;    /* Pointer to the next cidr */
	ipv4_cidr_t cidr;                /* CIDR */
} ipv4_match_list_t;

enum event_type {
	event_startup,
	event_cleanup,
	event_exit,
	event_signal,
	event_heartbeat,
};

typedef struct event {
	struct event *next;
	enum event_type type;
	int code;
} event_t;

typedef struct action {
	struct action *next;
	event_t *evt;
	char *command;
	char **env;
	int options;
	unsigned timeout;
	struct grecs_locus locus;
} action_t;

enum listener_status {
	stat_down,
	stat_up,
	stat_term,
	stat_onexit
};

#define REDIR_OUT 0
#define REDIR_ERR 1

typedef struct listener {                /* Listener */
	struct listener *prev;           /* Pointer to the previous listener */
	struct listener *next;           /* Pointer to the next listener */
	char *id;                        /* Listener id */
	struct interface *iface;         /* Network interface */
	ipv4_match_list_t *match_source; /* Source IP list (optional) */
	ipv4_match_list_t *match_dest;   /* Destination IP list (mandatory) */
	char *prog;                      /* Command to bring link up */
	char **env;                      /* Environment */
	int options;                     /* Execution options */

	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 */
	int progstat;                    /* Latest program termination
					    status */
	enum listener_status status;     /* Status of this listener */
	unsigned act_count;              /* Number of running actions in
					    stat_onexit state */

	int decommission;
} listener_t;


typedef struct {
	listener_t *head;
	listener_t *tail;
} listener_list_t;

enum process_type {
	type_listener,
	type_redirector,
	type_action
};

#define OPT_NOWAIT 0x01
#define OPT_STDOUT 0x02
#define OPT_STDERR 0x04
#define OPT_NULLIN 0x08

const char *ipv4_to_string(uint32_t ip);
int ipv4_match_p(ipv4_match_list_t *mp, uint32_t ip);
int ipv4_match_list_cmp(ipv4_match_list_t *a, ipv4_match_list_t *b);
void ipv4_match_list_free(ipv4_match_list_t *a);

int interfaces_init(void);
struct interface *interface_lookup(const char *name);
void interface_deinit(struct interface *ifp);
void interface_ref(struct interface *ifp);
void interface_unref(struct interface *ifp);
int interface_ok(struct interface *iface);

void interfaces_fdset(fd_set *fdset, int *fdmax);
void interfaces_poll(fd_set *fdset);
void interface_build_expr(struct interface *iface,
			  ipv4_match_list_t *match_source,
			  ipv4_match_list_t *match_dest);

void listener_list_add(listener_list_t *lst, listener_t *lp);
void listener_list_remove(listener_list_t *lst, listener_t *lp);
listener_t *listener_list_find_id(listener_list_t *lst, const char *id);
void listener_list_free(listener_list_t *lst);
void listener_list_concat(listener_list_t *a, listener_list_t *b);
int listener_list_run_action(listener_list_t *lst, int a);

void listener_fixup(listener_t *lp);
void listener_free(listener_t *lp);
void listener_decommission(listener_t *lp);
int listener_cmp(listener_t *a, listener_t *b);
listener_t *listener_locate(uint32_t src, uint32_t dst);
listener_t *listener_find_id(const char *id);
void listener_print_status(listener_t *lp);
void listener_proc_report(listener_t *lp);
void listener_kill_redirector(listener_t *lp, int what);
void listener_start(listener_t *lp, char **kve);
int listener_run_action(listener_t *lp, int a);

void onexit_reaction(listener_t *lp);

#define KVE_MINSIZE 7

void listener_kve_init(char **kve, int kvn, listener_t *lp, ...);


void listeners_init(void);
void listeners_cleanup(void);
int listeners_run_action(int a);
void listeners_decommission(void);
void listeners_undo_decommission(void);

extern listener_list_t llist;
extern listener_list_t clist;


#define EX_OK      0

struct ip;
void ip_handler(struct ip *, unsigned int);
void cons_ether_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
void cons_ppp_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
void cons_raw_packet(u_char *, const struct pcap_pkthdr *, const u_char *);

char **environ_setup(char **hint, char **kve);

int envcmp(char **a, char **b);
void envfree(char **a);


extern int proc_stop;
void progman_cleanup(void);

void progman_terminate(void);
int progman_start(int type, listener_t *lp, struct grecs_locus *loc,
		  int options, unsigned timeout,
		  char *prog, char **env, char **kve);
unsigned progman_expire(void);
struct timeval *progman_timeout(struct timeval *tv);
void progman_decommission(void);

Return to:

Send suggestions and report system problems to the System administrator.