usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / rc / qoslimit.c
blob90c965d65a5d243fbbd02332dd1c7bf90b95a4bf
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 int i, address_type;
80 //qosl is enabled?
81 if (!nvram_get_int("qosl_enable")) return;
83 //read qos1rules from nvram
84 g = buf = strdup(nvram_safe_get("qosl_rules"));
86 ibw = nvram_safe_get("qos_ibw"); // Read from QOS setting - KRP
87 obw = nvram_safe_get("qos_obw"); // Read from QOS setting - KRP
89 lanipaddr = nvram_safe_get("lan_ipaddr");
90 lanmask = nvram_safe_get("lan_netmask");
91 laninface = nvram_safe_get("lan_ifname");
94 //MANGLE
95 if (chain == 1)
97 ipt_write(
98 "-A PREROUTING -j IMQ -i %s --todev 1\n"
99 "-A POSTROUTING -j IMQ -o %s --todev 2\n"
100 ,laninface,laninface);
103 while (g) {
105 ipaddr_old<dlrate<dlceil<ulrate<ulceil<priority<tcplimit<udplimit
107 if ((p = strsep(&g, ">")) == NULL) break;
108 i = vstrsep(p, "<", &ipaddr_old, &dlrate, &dlceil, &ulrate, &ulceil, &priority, &tcplimit, &udplimit);
109 if (i!=8) continue;
111 priority_num = atoi(priority);
112 if ((priority_num < 0) || (priority_num > 5)) continue;
114 if (!strcmp(ipaddr_old,"")) continue;
116 address_checker (&address_type, ipaddr_old, ipaddr);
117 sprintf(seq,"%d",iSeq);
118 iSeq++;
120 if (!strcmp(dlceil,"")) strcpy(dlceil, dlrate);
121 if (strcmp(dlrate,"") && strcmp(dlceil, "")) {
122 if(chain == 1) {
123 switch (address_type)
125 case IP_ADDRESS:
126 ipt_write(
127 "-A POSTROUTING ! -s %s/%s -d %s -j MARK --set-mark %s\n"
128 ,lanipaddr,lanmask,ipaddr,seq);
129 break;
130 case MAC_ADDRESS:
131 break;
132 case IP_RANGE:
133 ipt_write(
134 "-A POSTROUTING ! -s %s/%s -m iprange --dst-range %s -j MARK --set-mark %s\n"
135 ,lanipaddr,lanmask,ipaddr,seq);
136 break;
141 if (!strcmp(ulceil,"")) strcpy(ulceil, ulrate);
142 if (strcmp(ulrate,"") && strcmp(ulceil, "")) {
143 if (chain == 1) {
144 switch (address_type)
146 case IP_ADDRESS:
147 ipt_write(
148 "-A PREROUTING -s %s ! -d %s/%s -j MARK --set-mark %s\n"
149 ,ipaddr,lanipaddr,lanmask,seq);
150 break;
151 case MAC_ADDRESS:
152 ipt_write(
153 "-A PREROUTING -m mac --mac-source %s ! -d %s/%s -j MARK --set-mark %s\n"
154 ,ipaddr,lanipaddr,lanmask,seq);
155 break;
156 case IP_RANGE:
157 ipt_write(
158 "-A PREROUTING -m iprange --src-range %s ! -d %s/%s -j MARK --set-mark %s\n"
159 ,ipaddr,lanipaddr,lanmask,seq);
160 break;
165 if(atoi(tcplimit) > 0){
166 if (chain == 2) {
167 switch (address_type)
169 case IP_ADDRESS:
170 ipt_write(
171 "-A PREROUTING -s %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
172 ,ipaddr,tcplimit);
173 break;
174 case MAC_ADDRESS:
175 ipt_write(
176 "-A PREROUTING -m mac --mac-source %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
177 ,ipaddr,tcplimit);
178 break;
179 case IP_RANGE:
180 ipt_write(
181 "-A PREROUTING -m iprange --src-range %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n"
182 ,ipaddr,tcplimit);
183 break;
187 if(atoi(udplimit) > 0){
188 if (chain == 2) {
189 switch (address_type)
191 case IP_ADDRESS:
192 ipt_write(
193 "-A PREROUTING -s %s -p udp -m limit --limit %s/sec -j ACCEPT\n"
194 ,ipaddr,udplimit);
195 break;
196 case MAC_ADDRESS:
197 ipt_write(
198 "-A PREROUTING -m mac --mac-source %s -p udp -m limit --limit %s/sec -j ACCEPT\n"
199 ,ipaddr,udplimit);
200 break;
201 case IP_RANGE:
202 ipt_write(
203 "-A PREROUTING -m iprange --src-range %s -p udp -m limit --limit %s/sec -j ACCEPT\n"
204 ,ipaddr,udplimit);
205 break;
210 free(buf);
213 // read nvram into files
214 void start_qoslimit(void)
216 FILE *tc;
217 char *buf;
218 char *g;
219 char *p;
220 char *ibw,*obw;//bandwidth
221 char seq[4];//mark number
222 int iSeq = 10;
223 char *ipaddr_old;
224 char ipaddr[30];//ip address
225 char *dlrate,*dlceil;//guaranteed rate & maximum rate for download
226 char *ulrate,*ulceil;//guaranteed rate & maximum rate for upload
227 char *priority;//priority
228 char *lanipaddr; //lan ip address
229 char *lanmask; //lan netmask
230 char *tcplimit,*udplimit;//tcp connection limit & udp packets per second
231 int priority_num;
232 int i, address_type;
233 int s[6];
235 //qosl is enabled?
236 if (!nvram_get_int("qosl_enable")) return;
238 //read qosl rules from nvram
239 g = buf = strdup(nvram_safe_get("qosl_rules"));
241 ibw = nvram_safe_get("qos_ibw"); // Read from QOS setting - KRP
242 obw = nvram_safe_get("qos_obw"); // Read from QOS setting - KRP
244 lanipaddr = nvram_safe_get("lan_ipaddr");
245 lanmask = nvram_safe_get("lan_netmask");
247 if ((tc = fopen(qoslimitfn, "w")) == NULL) return;
249 fprintf(tc,
250 "#!/bin/sh\n"
251 "ip link set imq1 up\n"
252 "ip link set imq2 up\n"
253 "\n"
254 "tc qdisc del dev imq1 root 2>/dev/null\n"
255 "tc qdisc del dev imq2 root 2>/dev/null\n"
256 "tc qdisc del dev br0 root 2>/dev/null\n" //fix me [why should mac get filter here??]
257 "\n"
258 "TCAM=\"tc class add dev br0\"\n" //fix me
259 "TFAM=\"tc filter add dev br0\"\n" //fix me
260 "TQAM=\"tc qdisc add dev br0\"\n" //fix me
261 "\n"
262 "TCA=\"tc class add dev imq2\"\n"
263 "TFA=\"tc filter add dev imq2\"\n"
264 "TQA=\"tc qdisc add dev imq2\"\n"
265 "\n"
266 "SFQ=\"sfq perturb 10\"\n"
267 "\n"
268 "TCAU=\"tc class add dev imq1\"\n"
269 "TFAU=\"tc filter add dev imq1\"\n"
270 "TQAU=\"tc qdisc add dev imq1\"\n"
271 "\n"
272 "tc qdisc add dev imq2 root handle 1: htb\n"
273 "tc class add dev imq2 parent 1: classid 1:1 htb rate %skbit\n"
274 "\n"
275 "tc qdisc add dev br0 root handle 1: htb\n"
276 "tc class add dev br0 parent 1: classid 1:1 htb rate %skbit\n"
277 "\n"
278 "tc qdisc add dev imq1 root handle 1: htb\n"
279 "tc class add dev imq1 parent 1: classid 1:1 htb rate %skbit\n"
280 "\n"
281 ,ibw,ibw,obw
284 while (g) {
286 ipaddr_old<dlrate<dlceil<ulrate<ulceil<priority<tcplimit<udplimit
288 if ((p = strsep(&g, ">")) == NULL) break;
289 i = vstrsep(p, "<", &ipaddr_old, &dlrate, &dlceil, &ulrate, &ulceil, &priority, &tcplimit, &udplimit);
290 if (i!=8) continue;
291 priority_num = atoi(priority);
292 if ((priority_num < 0) || (priority_num > 5)) continue;
293 if (!strcmp(ipaddr_old,"")) continue;
295 address_checker(&address_type, ipaddr_old, ipaddr);
296 sprintf(seq,"%d",iSeq);
297 iSeq++;
298 if (!strcmp(dlceil,"")) strcpy(dlceil, dlrate);
299 if (strcmp(dlrate,"") && strcmp(dlceil, "")) {
300 if (address_type != MAC_ADDRESS) {
301 fprintf(tc,
302 "$TCA parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n"
303 "$TQA parent 1:%s handle %s: $SFQ\n"
304 "$TFA parent 1:0 prio %s protocol ip handle %s fw flowid 1:%s\n"
305 "\n"
306 ,seq,dlrate,dlceil,priority
307 ,seq,seq
308 ,priority,seq,seq);
310 else if (address_type == MAC_ADDRESS ) {
311 sscanf(ipaddr, "%02X:%02X:%02X:%02X:%02X:%02X",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5]);
313 fprintf(tc,
314 "$TCAM parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n"
315 "$TQAM parent 1:%s handle %s: $SFQ\n"
316 "$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"
317 "\n"
318 ,seq,dlrate,dlceil,priority
319 ,seq,seq
320 ,priority,s[2],s[3],s[4],s[5],s[0],s[1],seq);
324 if (!strcmp(ulceil,"")) strcpy(ulceil, dlrate);
325 if (strcmp(ulrate,"") && strcmp(ulceil, "")) {
326 fprintf(tc,
327 "$TCAU parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n"
328 "$TQAU parent 1:%s handle %s: $SFQ\n"
329 "$TFAU parent 1:0 prio %s protocol ip handle %s fw flowid 1:%s\n"
330 "\n"
331 ,seq,ulrate,ulceil,priority
332 ,seq,seq
333 ,priority,seq,seq);
336 free(buf);
338 fclose(tc);
339 chmod(qoslimitfn, 0700);
341 //fake start
342 eval((char *)qoslimitfn, "start");
345 void stop_qoslimit(void)
347 FILE *f;
348 char *s = "/tmp/stop_qoslimittc.sh";
350 if ((f = fopen(s, "w")) == NULL) return;
352 fprintf(f,
353 "#!/bin/sh\n"
354 "tc qdisc del dev imq2 root\n"
355 "tc qdisc del dev imq1 root\n"
356 "tc qdisc del dev br0 root\n" //fix me
357 "ip link set imq1 down\n"
358 "ip link set imq2 down\n" //take imq's down - Toastman
360 "\n"
363 fclose(f);
364 chmod(s, 0700);
365 //fake stop
366 eval((char *)s, "stop");
370 PREROUTING (mn) ----> x ----> FORWARD (f) ----> + ----> POSTROUTING (n)
371 QD | ^
374 INPUT (f) OUTPUT (mnf)