Merge from master
[l2tpns.git] / throttlectl.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 /* throttle control */
10
11 int plugin_api_version = PLUGIN_API_VERSION;
12 static struct pluginfuncs *f = 0;
13
14 char *plugin_control_help[] = {
15 " throttle USER|SID [RATE|[in|out] RATE ...] Throttle user traffic",
16 " unthrottle USER|SID Stop throttling 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 int rate_in = 0;
27 int rate_out = 0;
28
29 if (data->argc < 1)
30 return PLUGIN_RET_OK;
31
32 if (strcmp(data->argv[0], "throttle") &&
33 strcmp(data->argv[0], "unthrottle"))
34 return PLUGIN_RET_OK; // not for us
35
36 if (!data->iam_master)
37 return PLUGIN_RET_NOTMASTER;
38
39 flag = data->argv[0][0] == 't';
40
41 if (flag)
42 {
43 if (data->argc < 2 || data->argc > 6)
44 {
45 data->response = NSCTL_RES_ERR;
46 data->additional = "requires username or session id and optional rate(s)";
47 return PLUGIN_RET_STOP;
48 }
49 }
50 else
51 {
52 if (data->argc != 2)
53 {
54 data->response = NSCTL_RES_ERR;
55 data->additional = "requires username or session id";
56 return PLUGIN_RET_STOP;
57 }
58 }
59
60 if (!(session = strtol(data->argv[1], &end, 10)) || *end)
61 session = f->get_session_by_username(data->argv[1]);
62
63 if (session)
64 s = f->get_session_by_id(session);
65
66 if (!s || !s->ip)
67 {
68 data->response = NSCTL_RES_ERR;
69 data->additional = "session not found";
70 return PLUGIN_RET_STOP;
71 }
72
73 if (flag)
74 {
75 rate_in = rate_out = -1;
76 if (data->argc == 2)
77 {
78 unsigned long *rate = f->getconfig("throttle_speed", UNSIGNED_LONG);
79 rate_in = rate_out = *rate;
80 }
81 else if (data->argc == 3)
82 {
83 rate_in = rate_out = atoi(data->argv[2]);
84 }
85 else
86 {
87 int i;
88 for (i = 2; i < data->argc - 1; i += 2)
89 {
90 int len = strlen(data->argv[i]);
91 if (!strncmp(data->argv[i], "in", len))
92 {
93 rate_in = atoi(data->argv[i+1]);
94 }
95 else if (!strncmp(data->argv[i], "out", len))
96 {
97 rate_out = atoi(data->argv[i+1]);
98 }
99 else
100 {
101 data->response = NSCTL_RES_ERR;
102 data->additional = "invalid rate";
103 return PLUGIN_RET_STOP;
104 }
105 }
106 }
107
108 if (!rate_in || !rate_out)
109 {
110 data->response = NSCTL_RES_ERR;
111 data->additional = "invalid rate";
112 return PLUGIN_RET_STOP;
113 }
114 }
115
116 if (rate_in != -1 && rate_in == s->throttle_in &&
117 rate_out != -1 && rate_out == s->throttle_out)
118 {
119 data->response = NSCTL_RES_ERR;
120 data->additional = flag ? "already throttled" : "not throttled";
121 return PLUGIN_RET_STOP;
122 }
123
124 f->throttle(session, rate_in, rate_out);
125 f->session_changed(session);
126
127 data->response = NSCTL_RES_OK;
128 data->additional = 0;
129
130 return PLUGIN_RET_STOP;
131 }
132
133 int plugin_init(struct pluginfuncs *funcs)
134 {
135 return ((f = funcs)) ? 1 : 0;
136 }