cf6508e772eee7e7e9e6faf14b1ac37985dc0732
[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 char const *cvs_id = "$Id: throttlectl.c,v 1.1 2004-11-17 15:08:19 bodea Exp $";
9
10 int plugin_api_version = PLUGIN_API_VERSION;
11 static struct pluginfuncs *p = 0;
12
13 char *plugin_control_help[] = {
14 " throttle USER|SID [RATE|[in|out] RATE ...] Throttle user traffic",
15 " unthrottle USER|SID Stop throttling user",
16 0
17 };
18
19 static int iam_master = 0;
20
21 int plugin_init(struct pluginfuncs *funcs)
22 {
23 if (!funcs)
24 return 0;
25
26 p = funcs;
27 return 1;
28 }
29
30 int plugin_become_master(void)
31 {
32 iam_master = 1;
33 return PLUGIN_RET_OK;
34 }
35
36 int plugin_control(struct param_control *data)
37 {
38 sessionidt session;
39 sessiont *s = 0;
40 int flag;
41 char *end;
42 int rate_in = 0;
43 int rate_out = 0;
44
45 if (data->argc < 1)
46 return PLUGIN_RET_OK;
47
48 if (strcmp(data->argv[0], "throttle")
49 && strcmp(data->argv[0], "unthrottle"))
50 return PLUGIN_RET_OK; // not for us
51
52 flag = data->argv[0][0] != 'g';
53
54 if (!iam_master)
55 {
56 data->response = NSCTL_RES_ERR;
57 data->additional = "must be run on the cluster master";
58 return PLUGIN_RET_STOP;
59 }
60
61 if (flag)
62 {
63 if (data->argc < 2 || data->argc > 4)
64 {
65 data->response = NSCTL_RES_ERR;
66 data->additional = "requires username or session id and optional rate(s)";
67 return PLUGIN_RET_STOP;
68 }
69 }
70 else
71 {
72 if (data->argc != 2)
73 {
74 data->response = NSCTL_RES_ERR;
75 data->additional = "requires username or session id";
76 return PLUGIN_RET_STOP;
77 }
78 }
79
80 if (!(session = strtol(data->argv[1], &end, 10)) || *end)
81 session = p->get_session_by_username(data->argv[1]);
82
83 if (session)
84 s = p->get_session_by_id(session);
85
86 if (!s || !s->ip)
87 {
88 data->response = NSCTL_RES_ERR;
89 data->additional = "session not found";
90 return PLUGIN_RET_STOP;
91 }
92
93 if (flag)
94 {
95 rate_in = rate_out = -1;
96 if (data->argc == 2)
97 {
98 unsigned long *rate = p->getconfig("throttle_speed", UNSIGNED_LONG);
99 rate_in = rate_out = *rate;
100 }
101 else if (data->argc == 3)
102 {
103 rate_in = rate_out = atoi(data->argv[2]);
104 }
105 else
106 {
107 int i;
108 for (i = 2; i < data->argc - 1; i += 2)
109 {
110 int len = strlen(data->argv[i]);
111 if (!strncmp(data->argv[i], "in", len))
112 {
113 rate_in = atoi(argv[i+1]);
114 }
115 else if (!strncmp(data->argv[i], "out", len))
116 {
117 rate_out = atoi(argv[i+1]);
118 }
119 else
120 {
121 data->response = NSCTL_RES_ERR;
122 data->additional = "invalid rate";
123 return PLUGIN_RET_STOP;
124 }
125 }
126 }
127
128 if (!rate_in || !rate_out)
129 {
130 data->response = NSCTL_RES_ERR;
131 data->additional = "invalid rate";
132 return PLUGIN_RET_STOP;
133 }
134 }
135
136 if (rate_in != -1 && rate_in == s->throttle_in &&
137 rate_out != -1 && rate_out == s->throttle_out)
138 {
139 data->response = NSCTL_RES_ERR;
140 data->additional = flag ? "already throttled" : "not throttled";
141 return PLUGIN_RET_STOP;
142 }
143
144 p->throttle(session, rate_in, rate_out);
145 p->sesssion_changed(session);
146
147 data->response = NSCTL_RES_OK;
148 data->additional = 0;
149
150 return PLUGIN_RET_STOP;
151 }