Reinstate dropbear 0.54 update
[tomato.git] / release / src / router / rc / qoslimit.c
blob2ba7b776252f1c85ea31e2b7d691890148f59146
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2008 Jonathan Zarate
5 Copyright (C) 2011 Deon 'PrinceAMD' Thomas
6 rate limit & connection limit by conanxu
7 */
9 #include "rc.h"
11 #include <sys/stat.h>
12 static const char *qoslimitfn = "/etc/qoslimit";
14 /*int chain
15 1 = MANGLE
16 2 = NAT
19 #define IP_ADDRESS 0
20 #define MAC_ADDRESS 1
21 #define IP_RANGE 2
23 void address_checker (int * address_type, char *ipaddr_old, char *ipaddr)
25 char * second_part, *last_dot;
26 int length_to_minus, length_to_dot;
28 second_part = strchr(ipaddr_old, '-');
29 if (second_part != NULL) {
30 /* ip range */
31 *address_type = IP_RANGE;
32 if (strchr(second_part+1, '.') != NULL) {
33 /* long notation */
34 strcpy (ipaddr, ipaddr_old);
36 else {
37 /* short notation */
38 last_dot = strrchr(ipaddr_old, '.');
39 length_to_minus = second_part - ipaddr_old;
40 length_to_dot = last_dot- ipaddr_old;
41 strncpy(ipaddr, ipaddr_old, length_to_minus + 1);
42 strncpy(ipaddr + length_to_minus + 1, ipaddr, length_to_dot + 1);
43 strcpy(ipaddr + length_to_minus + length_to_dot + 2, second_part +1);
46 else {
47 /* mac address of ipaddres */
48 if (strlen(ipaddr_old) != 17) {
49 /* IP_ADDRESS */
50 *address_type = IP_ADDRESS;
52 else {
53 /* MAC ADDRESS */
54 *address_type = MAC_ADDRESS;
56 strcpy (ipaddr, ipaddr_old);
60 void ipt_qoslimit(int chain)
62 char *buf;
63 char *g;
64 char *p;
65 char *ibw,*obw;//bandwidth
66 char seq[4];//mark number
67 int iSeq = 10;
68 char *ipaddr_old;
69 char ipaddr[30];//ip address
70 char *dlrate,*dlceil;//guaranteed rate & maximum rate for download
71 char *ulrate,*ulceil;//guaranteed rate & maximum rate for upload
72 char *priority;//priority
73 char *lanipaddr; //lan ip address
74 char *lanmask; //lan netmask
75 char *tcplimit,*udplimit;//tcp connection limit & udp packets per second
76 char *laninface; // lan interface
77 int priority_num;
78 char *qosl_dtcp,*qosl_dudp;
79 int i, address_type;
81 //qosl is enabled?
82 if (!nvram_get_int("qosl_enable")) return;
84 //read qos1rules from nvram
85 g = buf = strdup(nvram_safe_get("qosl_rules"));
87 ibw = nvram_safe_get("qos_ibw"); // Read from QOS setting - KRP
88 obw = nvram_safe_get("qos_obw"); // Read from QOS setting - KRP
90 lanipaddr = nvram_safe_get("lan_ipaddr");
91 lanmask = nvram_safe_get("lan_netmask");
92 laninface = nvram_safe_get("lan_ifname");
94 qosl_dtcp = nvram_safe_get("qosl_dtcp");
95 qosl_dudp = nvram_safe_get("qosl_dudp");
97 //MANGLE
98 if (chain == 1)
100 ipt_write(
101 "-A PREROUTING -j IMQ -i %s --todev 1\n"
102 "-A POSTROUTING -j IMQ -o %s --todev 2\n"
103 ,laninface,laninface);
104 if (nvram_get_int("qosl_denable") == 1) {
105 ipt_write(
106 "-A POSTROUTING ! -s %s/%s -j MARK --set-mark 100\n"
107 "-A PREROUTING ! -d %s/%s -j MARK --set-mark 100\n"
108 ,lanipaddr,lanmask
109 ,lanipaddr,lanmask);
113 //NAT
114 if (chain == 2)
116 if (nvram_get_int("qosl_denable") == 1) {
117 if (nvram_get_int("qosl_dtcp") > 0) {
118 ipt_write(
119 "-A PREROUTING -s %s/%s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
120 ,lanipaddr,lanmask,qosl_dtcp);
123 if (nvram_get_int("qosl_dudp") > 0) {
124 ipt_write(
125 "-A PREROUTING -s %s/%s -p udp -m limit --limit %s/sec -j ACCEPT\n"
126 ,lanipaddr,lanmask,qosl_dudp);
131 while (g) {
133 ipaddr_old<dlrate<dlceil<ulrate<ulceil<priority<tcplimit<udplimit
135 if ((p = strsep(&g, ">")) == NULL) break;
136 i = vstrsep(p, "<", &ipaddr_old, &dlrate, &dlceil, &ulrate, &ulceil, &priority, &tcplimit, &udplimit);
137 if (i!=8) continue;
139 priority_num = atoi(priority);
140 if ((priority_num < 0) || (priority_num > 5)) continue;
142 if (!strcmp(ipaddr_old,"")) continue;
144 address_checker (&address_type, ipaddr_old, ipaddr);
145 sprintf(seq,"%d",iSeq);
146 iSeq++;
148 if (!strcmp(dlceil,"")) strcpy(dlceil, dlrate);
149 if (strcmp(dlrate,"") && strcmp(dlceil, "")) {
150 if(chain == 1) {
151 switch (address_type)
153 case IP_ADDRESS:
154 ipt_write(
155 "-A POSTROUTING ! -s %s/%s -d %s -j MARK --set-mark %s\n"
156 ,lanipaddr,lanmask,ipaddr,seq);
157 break;
158 case MAC_ADDRESS:
159 break;
160 case IP_RANGE:
161 ipt_write(
162 "-A POSTROUTING ! -s %s/%s -m iprange --dst-range %s -j MARK --set-mark %s\n"
163 ,lanipaddr,lanmask,ipaddr,seq);
164 break;
169 if (!strcmp(ulceil,"")) strcpy(ulceil, ulrate);
170 if (strcmp(ulrate,"") && strcmp(ulceil, "")) {
171 if (chain == 1) {
172 switch (address_type)
174 case IP_ADDRESS:
175 ipt_write(
176 "-A PREROUTING -s %s ! -d %s/%s -j MARK --set-mark %s\n"
177 ,ipaddr,lanipaddr,lanmask,seq);
178 break;
179 case MAC_ADDRESS:
180 ipt_write(
181 "-A PREROUTING -m mac --mac-source %s ! -d %s/%s -j MARK --set-mark %s\n"
182 ,ipaddr,lanipaddr,lanmask,seq);
183 break;
184 case IP_RANGE:
185 ipt_write(
186 "-A PREROUTING -m iprange --src-range %s ! -d %s/%s -j MARK --set-mark %s\n"
187 ,ipaddr,lanipaddr,lanmask,seq);
188 break;
193 if(atoi(tcplimit) > 0){
194 if (chain == 2) {
195 switch (address_type)
197 case IP_ADDRESS:
198 ipt_write(
199 "-A PREROUTING -s %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
200 ,ipaddr,tcplimit);
201 break;
202 case MAC_ADDRESS:
203 ipt_write(
204 "-A PREROUTING -m mac --mac-source %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
205 ,ipaddr,tcplimit);
206 break;
207 case IP_RANGE:
208 ipt_write(
209 "-A PREROUTING -m iprange --src-range %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
210 ,ipaddr,tcplimit);
211 break;
215 if(atoi(udplimit) > 0){
216 if (chain == 2) {
217 switch (address_type)
219 case IP_ADDRESS:
220 ipt_write(
221 "-A PREROUTING -s %s -p udp -m limit --limit %s/sec -j ACCEPT\n"
222 ,ipaddr,udplimit);
223 break;
224 case MAC_ADDRESS:
225 ipt_write(
226 "-A PREROUTING -m mac --mac-source %s -p udp -m limit --limit %s/sec -j ACCEPT\n"
227 ,ipaddr,udplimit);
228 break;
229 case IP_RANGE:
230 ipt_write(
231 "-A PREROUTING -m iprange --src-range %s -p udp -m limit --limit %s/sec -j ACCEPT\n"
232 ,ipaddr,udplimit);
233 break;
238 free(buf);
241 // read nvram into files
242 void start_qoslimit(void)
244 FILE *tc;
245 char *buf;
246 char *g;
247 char *p;
248 char *ibw,*obw;//bandwidth
249 char seq[4];//mark number
250 int iSeq = 10;
251 char *ipaddr_old;
252 char ipaddr[30];//ip address
253 char *dlrate,*dlceil;//guaranteed rate & maximum rate for download
254 char *ulrate,*ulceil;//guaranteed rate & maximum rate for upload
255 char *priority;//priority
256 char *lanipaddr; //lan ip address
257 char *lanmask; //lan netmask
258 char *tcplimit,*udplimit;//tcp connection limit & udp packets per second
259 int priority_num;
260 char *ddlr,*ddlc,*dulr,*dulc; //download / upload - rate / ceiling
261 int i, address_type;
262 int s[6];
264 //qosl is enabled?
265 if (!nvram_get_int("qosl_enable")) return;
267 //read qosl rules from nvram
268 g = buf = strdup(nvram_safe_get("qosl_rules"));
270 ibw = nvram_safe_get("qos_ibw"); // Read from QOS setting - KRP
271 obw = nvram_safe_get("qos_obw"); // Read from QOS setting - KRP
273 lanipaddr = nvram_safe_get("lan_ipaddr");
274 lanmask = nvram_safe_get("lan_netmask");
276 ddlr = nvram_safe_get("qosl_ddlr"); //Default download rate
277 ddlc = nvram_safe_get("qosl_ddlc"); //Default download ceiling
278 dulr = nvram_safe_get("qosl_dulr"); //Default upload rate
279 dulc = nvram_safe_get("qosl_dulc"); //Default upload ceiling
281 if ((tc = fopen(qoslimitfn, "w")) == NULL) return;
283 fprintf(tc,
284 "#!/bin/sh\n"
285 "ip link set imq1 up\n"
286 "ip link set imq2 up\n"
287 "\n"
288 "tc qdisc del dev imq1 root 2>/dev/null\n"
289 "tc qdisc del dev imq2 root 2>/dev/null\n"
290 "tc qdisc del dev br0 root 2>/dev/null\n" //fix me [why should mac get filter here??]
291 "\n"
292 "TCAM=\"tc class add dev br0\"\n" //fix me
293 "TFAM=\"tc filter add dev br0\"\n" //fix me
294 "TQAM=\"tc qdisc add dev br0\"\n" //fix me
295 "\n"
296 "TCA=\"tc class add dev imq2\"\n"
297 "TFA=\"tc filter add dev imq2\"\n"
298 "TQA=\"tc qdisc add dev imq2\"\n"
299 "\n"
300 "SFQ=\"sfq perturb 10\"\n"
301 "\n"
302 "TCAU=\"tc class add dev imq1\"\n"
303 "TFAU=\"tc filter add dev imq1\"\n"
304 "TQAU=\"tc qdisc add dev imq1\"\n"
305 "\n"
306 "tc qdisc add dev imq2 root handle 1: htb\n"
307 "tc class add dev imq2 parent 1: classid 1:1 htb rate %skbit\n"
308 "\n"
309 "tc qdisc add dev br0 root handle 1: htb\n"
310 "tc class add dev br0 parent 1: classid 1:1 htb rate %skbit\n"
311 "\n"
312 "tc qdisc add dev imq1 root handle 1: htb\n"
313 "tc class add dev imq1 parent 1: classid 1:1 htb rate %skbit\n"
314 "\n"
315 ,ibw,ibw,obw
318 if ((nvram_get_int("qosl_denable") == 1) && strcmp(ddlr,"") && strcmp(dulr,"")) {
319 if (!strcmp(ddlc,"")) strcpy(ddlc, ddlr);
320 if (!strcmp(dulc,"")) strcpy(dulc, dulr);
321 fprintf(tc,
322 "$TCA parent 1:1 classid 1:100 htb rate %skbit ceil %skbit prio 3\n"
323 "$TQA parent 1:100 handle 100: $SFQ\n"
324 "$TFA parent 1:0 prio 3 protocol ip handle 100 fw flowid 1:100\n"
325 "\n"
326 "$TCAU parent 1:1 classid 1:100 htb rate %skbit ceil %skbit prio 3\n"
327 "$TQAU parent 1:100 handle 100: $SFQ\n"
328 "$TFAU parent 1:0 prio 3 protocol ip handle 100 fw flowid 1:100\n"
329 "\n"
330 ,ddlr,ddlc
331 ,dulr,dulc);
334 while (g) {
336 ipaddr_old<dlrate<dlceil<ulrate<ulceil<priority<tcplimit<udplimit
338 if ((p = strsep(&g, ">")) == NULL) break;
339 i = vstrsep(p, "<", &ipaddr_old, &dlrate, &dlceil, &ulrate, &ulceil, &priority, &tcplimit, &udplimit);
340 if (i!=8) continue;
341 priority_num = atoi(priority);
342 if ((priority_num < 0) || (priority_num > 5)) continue;
343 if (!strcmp(ipaddr_old,"")) continue;
345 address_checker(&address_type, ipaddr_old, ipaddr);
346 sprintf(seq,"%d",iSeq);
347 iSeq++;
348 if (!strcmp(dlceil,"")) strcpy(dlceil, dlrate);
349 if (strcmp(dlrate,"") && strcmp(dlceil, "")) {
350 if (address_type != MAC_ADDRESS) {
351 fprintf(tc,
352 "$TCA parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n"
353 "$TQA parent 1:%s handle %s: $SFQ\n"
354 "$TFA parent 1:0 prio %s protocol ip handle %s fw flowid 1:%s\n"
355 "\n"
356 ,seq,dlrate,dlceil,priority
357 ,seq,seq
358 ,priority,seq,seq);
360 else if (address_type == MAC_ADDRESS ) {
361 sscanf(ipaddr, "%02X:%02X:%02X:%02X:%02X:%02X",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5]);
363 fprintf(tc,
364 "$TCAM parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n"
365 "$TQAM parent 1:%s handle %s: $SFQ\n"
366 "$TFAM parent 1:0 protocol ip prio %s u32 match u16 0x0800 0xFFFF at -2 match u32 0x%02X%02X%02X%02X 0xFFFFFFFF at -12 match u16 0x%02X%02X 0xFFFF at -14 flowid 1:%s\n"
367 "\n"
368 ,seq,dlrate,dlceil,priority
369 ,seq,seq
370 ,priority,s[2],s[3],s[4],s[5],s[0],s[1],seq);
374 if (!strcmp(ulceil,"")) strcpy(ulceil, dlrate);
375 if (strcmp(ulrate,"") && strcmp(ulceil, "")) {
376 fprintf(tc,
377 "$TCAU parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n"
378 "$TQAU parent 1:%s handle %s: $SFQ\n"
379 "$TFAU parent 1:0 prio %s protocol ip handle %s fw flowid 1:%s\n"
380 "\n"
381 ,seq,ulrate,ulceil,priority
382 ,seq,seq
383 ,priority,seq,seq);
386 free(buf);
388 fclose(tc);
389 chmod(qoslimitfn, 0700);
391 //fake start
392 eval((char *)qoslimitfn, "start");
395 void stop_qoslimit(void)
397 FILE *f;
398 char *s = "/tmp/stop_qoslimittc.sh";
400 if ((f = fopen(s, "w")) == NULL) return;
402 fprintf(f,
403 "#!/bin/sh\n"
404 "tc qdisc del dev imq2 root\n"
405 "tc qdisc del dev imq1 root\n"
406 "tc qdisc del dev br0 root\n" //fix me
407 "ip link set imq1 down\n"
408 "ip link set imq2 down\n" //take imq's down - Toastman
410 "\n"
413 fclose(f);
414 chmod(s, 0700);
415 //fake stop
416 eval((char *)s, "stop");
420 PREROUTING (mn) ----> x ----> FORWARD (f) ----> + ----> POSTROUTING (n)
421 QD | ^
424 INPUT (f) OUTPUT (mnf)