Fix: No RADIUS Stop message sent (regression due to the patch to avoid sending multip...
[l2tpns.git] / throttlectl.c
1 #include <string.h>
2 #include "l2tpns.h"
3 #include "plugin.h"
4 #include "control.h"
5
6 /* throttle control */
7
8 int plugin_api_version = PLUGIN_API_VERSION;
9 static struct pluginfuncs *f = 0;
10
11 char *plugin_control_help[] = {
12 " throttle USER|SID [RATE|[in|out] RATE ...] Throttle user traffic",
13 " unthrottle USER|SID Stop throttling user",
14 0
15 };
16
17 int plugin_control(struct param_control *data)
18 {
19 sessionidt session;
20 sessiont *s = 0;
21 int flag;
22 char *end;
23 int rate_in = 0;
24 int rate_out = 0;
25
26 if (data->argc < 1)
27 return PLUGIN_RET_OK;
28
29 if (strcmp(data->argv[0], "throttle") &&
30 strcmp(data->argv[0], "unthrottle"))
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] == 't';
37
38 if (flag)
39 {
40 if (data->argc < 2 || data->argc > 6)
41 {
42 data->response = NSCTL_RES_ERR;
43 data->additional = "requires username or session id and optional rate(s)";
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 rate_in = rate_out = -1;
73 if (data->argc == 2)
74 {
75 unsigned long *rate = f->getconfig("throttle_speed", UNSIGNED_LONG);
76 rate_in = rate_out = *rate;
77 }
78 else if (data->argc == 3)
79 {
80 rate_in = rate_out = atoi(data->argv[2]);
81 }
82 else
83 {
84 int i;
85 for (i = 2; i < data->argc - 1; i += 2)
86 {
87 int len = strlen(data->argv[i]);
88 if (!strncmp(data->argv[i], "in", len))
89 {
90 rate_in = atoi(data->argv[i+1]);
91 }
92 else if (!strncmp(data->argv[i], "out", len))
93 {
94 rate_out = atoi(data->argv[i+1]);
95 }
96 else
97 {
98 data->response = NSCTL_RES_ERR;
99 data->additional = "invalid rate";
100 return PLUGIN_RET_STOP;
101 }
102 }
103 }
104
105 if (!rate_in || !rate_out)
106 {
107 data->response = NSCTL_RES_ERR;
108 data->additional = "invalid rate";
109 return PLUGIN_RET_STOP;
110 }
111 }
112
113 if (rate_in != -1 && rate_in == s->throttle_in &&
114 rate_out != -1 && rate_out == s->throttle_out)
115 {
116 data->response = NSCTL_RES_ERR;
117 data->additional = flag ? "already throttled" : "not throttled";
118 return PLUGIN_RET_STOP;
119 }
120
121 f->throttle(session, rate_in, rate_out);
122 f->session_changed(session);
123
124 data->response = NSCTL_RES_OK;
125 data->additional = 0;
126
127 return PLUGIN_RET_STOP;
128 }
129
130 int plugin_init(struct pluginfuncs *funcs)
131 {
132 return ((f = funcs)) ? 1 : 0;
133 }