Merge from master
[l2tpns.git] / snoopctl.c
1 #include <string.h>
2 #include <sys/socket.h>
3 #include <linux/rtnetlink.h>
4
5 #include "l2tpns.h"
6 #include "plugin.h"
7 #include "control.h"
8
9 /* snoop control */
10
11 int plugin_api_version = PLUGIN_API_VERSION;
12 static struct pluginfuncs *f = 0;
13
14 char *plugin_control_help[] = {
15 " snoop USER|SID IP PORT Intercept user traffic",
16 " unsnoop USER|SID Stop intercepting user",
17 0
18 };
19
20 int plugin_control(struct param_control *data)
21 {
22 sessionidt session;
23 sessiont *s = 0;
24 int flag;
25 char *end;
26
27 if (data->argc < 1)
28 return PLUGIN_RET_OK;
29
30 if (strcmp(data->argv[0], "snoop") && strcmp(data->argv[0], "unsnoop"))
31 return PLUGIN_RET_OK; // not for us
32
33 if (!data->iam_master)
34 return PLUGIN_RET_NOTMASTER;
35
36 flag = data->argv[0][0] != 'u';
37
38 if (flag)
39 {
40 if (data->argc != 4)
41 {
42 data->response = NSCTL_RES_ERR;
43 data->additional = "requires username or session id and host, port";
44 return PLUGIN_RET_STOP;
45 }
46 }
47 else
48 {
49 if (data->argc != 2)
50 {
51 data->response = NSCTL_RES_ERR;
52 data->additional = "requires username or session id";
53 return PLUGIN_RET_STOP;
54 }
55 }
56
57 if (!(session = strtol(data->argv[1], &end, 10)) || *end)
58 session = f->get_session_by_username(data->argv[1]);
59
60 if (session)
61 s = f->get_session_by_id(session);
62
63 if (!s || !s->ip)
64 {
65 data->response = NSCTL_RES_ERR;
66 data->additional = "session not found";
67 return PLUGIN_RET_STOP;
68 }
69
70 if (flag)
71 {
72 in_addr_t ip = inet_addr(data->argv[2]);
73 uint16_t port = atoi(data->argv[3]);
74
75 if (!ip || ip == INADDR_NONE)
76 {
77 data->response = NSCTL_RES_ERR;
78 data->additional = "invalid ip address";
79 return PLUGIN_RET_STOP;
80 }
81
82 if (!port)
83 {
84 data->response = NSCTL_RES_ERR;
85 data->additional = "invalid port";
86 return PLUGIN_RET_STOP;
87 }
88
89 if (ip == s->snoop_ip && port == s->snoop_port)
90 {
91 data->response = NSCTL_RES_ERR;
92 data->additional = "already intercepted";
93 return PLUGIN_RET_STOP;
94 }
95
96 s->snoop_ip = ip;
97 s->snoop_port = port;
98 }
99 else
100 {
101 if (!s->snoop_ip)
102 {
103 data->response = NSCTL_RES_ERR;
104 data->additional = "not intercepted";
105 return PLUGIN_RET_STOP;
106 }
107
108 s->snoop_ip = 0;
109 s->snoop_port = 0;
110 }
111
112 f->session_changed(session);
113
114 data->response = NSCTL_RES_OK;
115 data->additional = 0;
116
117 return PLUGIN_RET_STOP;
118 }
119
120 int plugin_init(struct pluginfuncs *funcs)
121 {
122 return ((f = funcs)) ? 1 : 0;
123 }