1#ifdef QOS
2#include<stdio.h>
3#include<stdlib.h>
4#include <limits.h>
5#include <time.h>
6#include <unistd.h>
7#include <errno.h>
8#include <syslog.h>
9#include <signal.h>
10#include <string.h>
11#include <sys/klog.h>
12#include <sys/types.h>
13#include <sys/mount.h>
14#include <sys/reboot.h>
15#include <sys/stat.h>
16#include <sys/sysmacros.h>
17#include <sys/time.h>
18#include <sys/utsname.h>
19#include <sys/wait.h>
20#include <sys/socket.h>
21#include <net/if_arp.h>
22#include <dirent.h>
23
24#ifdef ASUS_RC
25#include<asusbcmnvram.h>
26#else
27#include <epivers.h>
28#include<bcmnvram.h>
29#endif
30
31#include <shutils.h>
32FILE *fp=NULL;
33
34/***************************************************************************************/
35//  The definitions of all partations
36//    10:1 root class for upload
37//    10:2 root class for download
38//    10:10 partation for tos(bit 4)	& short pkt 	& psh
39//    10:20 partation for tos(bit 3)	& UD(high)
40//    10:30 partation for tos(bit 2)	& application
41//    10:40 partation for ftp on router& UD(middle)
42//    10:50 partation for tos(bit 1)
43//    10:60 default class
44//    10:70 partation for UD(low)
45//    10:80 partation only for vlan
46/***************************************************************************************/
47
48void tc_class_global(char *network, char *idx, char *minBW, char *maxBW, char *prio_level)
49{
50	char flowid[32];
51        char filter_handle[32];
52	char handle[32];
53
54        sprintf(flowid, "%s%s", "10:", idx);
55        sprintf(handle, "%s%s%s", "1", idx, ":");
56        sprintf(filter_handle, "%s", idx);
57
58        eval("tc","class","add","dev",network,"parent","10:1","classid",flowid,"htb","rate",\
59		minBW,"ceil",maxBW, "prio", prio_level);
60        eval("tc","qdisc","add","dev",network,"parent",flowid,"handle",handle,"pfifo");
61        eval("tc","filter","add","dev",network,"parent","10:", "protocol", "ip", "prio", \
62		prio_level,"handle", filter_handle, "fw", "classid", flowid);
63#ifdef QOS_DEBUG
64        syslog(LOG_NOTICE, "tc class add dev %s parent 10:1 classid %s htb rate %s ceil %s prio %s\n",\
65		network, flowid, minBW, maxBW, prio_level);
66        syslog(LOG_NOTICE, "tc qdisc add dev %s parent %s handle %s pfifo\n", network, flowid, handle);
67        syslog(LOG_NOTICE, "tc filter add dev %s parent 10: protocol ip prio %s handle %s fw classid %s\n",\
68		network, prio_level, filter_handle, flowid);
69	printf("tc class add dev %s parent 10:1 classid %s htb rate %s ceil %s prio %s\n", network,\
70		flowid, minBW, maxBW, prio_level);
71        printf("tc qdisc add dev %s parent %s handle %s pfifo\n", network, flowid, handle);
72        printf("tc filter add dev %s parent 10: protocol ip prio %s handle %s fw classid %s\n", network,\
73		prio_level, filter_handle, flowid);
74#endif
75}
76
77/************************************************************************************/
78/* This function is to add the filter match user specify. For LAN IP address, the   */
79/* interface should be br0. For WAN IP address, the interface should be eth0/ppp0   */
80/************************************************************************************/
81char *Ch_conv(char *proto_name, int idx)
82{
83	char *proto;
84	char qos_name_x[32];
85	sprintf(qos_name_x, "%s%d", proto_name, idx);
86	if (nvram_match(qos_name_x,""))
87	{
88		return NULL;
89	}
90	else
91	{
92		proto=nvram_get(qos_name_x);
93		return proto;
94	}
95}
96
97void tc_filter(char *ipaddr, char *port, int prio)
98{
99	int user_mark;
100	user_mark= prio*10;
101
102	if (port == NULL)
103	{
104		fprintf(fp, "-A POSTROUTING -s %s -j MARK --set-mark %d\n", ipaddr, user_mark);
105		fprintf(fp, "-A POSTROUTING -s %s -j RETURN\n", ipaddr);
106	}
107	else if (ipaddr == NULL)
108	{
109		fprintf(fp, "-A POSTROUTING -p tcp --dport %s -j MARK --set-mark %d\n", port, user_mark);
110		fprintf(fp, "-A POSTROUTING -p tcp --dport %s -j RETURN\n", port);
111		fprintf(fp, "-A POSTROUTING -p udp --dport %s -j MARK --set-mark %d\n", port, user_mark);
112		fprintf(fp, "-A POSTROUTING -p udp --dport %s -j RETURN\n", port);
113	}
114	else
115	{
116		fprintf(fp, "-A POSTROUTING -s %s -p tcp --dport %s -j MARK --set-mark %d\n", ipaddr, port, user_mark);
117		fprintf(fp, "-A POSTROUTING -s %s -p tcp --dport %s -j RETURN\n", ipaddr, port);
118		fprintf(fp, "-A POSTROUTING -s %s -p udp --dport %s -j MARK --set-mark %d\n",ipaddr, port, user_mark);
119		fprintf(fp, "-A POSTROUTING -s %s -p udp --dport %s -j RETURN\n", ipaddr, port);
120	}
121}
122
123void start_qos(char *wan_ipaddr)	//modified by angela 2008.05
124{
125	int rulenum=0;
126	int idx_class=0, idx_filter=0, idx_class_S=0; // control index
127	int idx=0;
128	char net_name[32], net_down_name[32];
129	char qos_name[32];
130	int ubw=0, service_ubw=0;
131	char qos_ubw[32],qos_min_ubw[32], qos_data_ubw[32], qos_down_ubw[32],qos_down[32];
132	char dfragment_size[32];
133	int flag=0;
134
135	//Open file for writing iptables rules
136	if ((fp=fopen("/tmp/mangle_rules", "w"))==NULL) return;
137	fprintf(fp, "*mangle\n");
138
139	/*Enable Dynamic Fragmentation function*/
140	//536 =  standard MTU(576) - IP header(20) - TCP header(20)
141	//1200 = suggested trasmmit packet size
142	if( nvram_match("qos_dfragment_enable", "1")) {
143		int mss_size = 1200;
144		float pct = atoi(nvram_get("qos_dfragment_size"));
145		pct = pct/100;
146		mss_size = 536 + (1200-536)*pct;
147
148		//packet size % 4 Must equl 0 (no padding octets)
149		if(mss_size%4)
150			mss_size = (mss_size/4 +1) *4;
151
152		//536 =  standard MTU(576) - IP header(20) - TCP header(20)
153		//1200 = suggested trasmmit packet size
154		sprintf(dfragment_size, "%d", mss_size);
155
156		fprintf(fp, "-A POSTROUTING -p tcp --tcp-flags SYN,ACK SYN,ACK -j TCPMSS --set-mss %s\n", dfragment_size);
157	}
158
159	if(nvram_invmatch("qos_global_enable", "1")
160			&& nvram_invmatch("qos_userspec_app", "1")
161			)
162		goto QOS_END;
163
164	nvram_set("qos_XXX", "1");
165	rulenum=atoi(nvram_safe_get("qos_rulenum_x"));
166
167// 2009.10 James. {
168	fprintf(fp, "-A POSTROUTING -d %s/%s -j MARK --set-mark 80\n", nvram_safe_get("lan_ipaddr_t"), nvram_safe_get("lan_netmask_t"));
169	fprintf(fp, "-A POSTROUTING -d %s/%s -j RETURN\n", nvram_safe_get("lan_ipaddr_t"), nvram_safe_get("lan_netmask_t"));
170// 2009.10 James. }
171
172	/* Get interface name */
173	if (nvram_match("wan0_proto", "pppoe") || nvram_match("wan0_proto", "pptp") || nvram_match("wan0_proto", "l2tp"))
174		strcpy (net_name, nvram_safe_get("wan0_pppoe_ifname"));
175	else
176		strcpy (net_name, nvram_safe_get("wan0_ifname"));
177
178	/* Add new qdisc for wan classify */
179	if(nvram_match("qos_pshack_prio", "1")||nvram_match("qos_tos_prio", "1"))
180		eval("tc","qdisc","add", "dev", net_name, "root", "handle", "10:",\
181			 "htb", "default", "10");
182	else
183		eval("tc","qdisc","add", "dev", net_name, "root", "handle", "10:",\
184			 "htb", "default", "50");
185
186#ifdef GPQOS
187	// Add root class 10:2 and BW = unlimited
188	eval("tc", "class", "add", "dev", net_name, "parent", "10:", "classid", "10:2",\
189		 "htb", "rate", "100000kbit", "ceil", "100000kbit");
190
191	// Add class 10:80 for local web access
192// 2009.10 James. {
193//       	char lan_ipaddr[32];
194//        sprintf(lan_ipaddr, "%s%s", nvram_get("lan_ipaddr"), "/24");
195// 2009.10 James. }
196
197	eval("tc", "class", "add", "dev", net_name, "parent", "10:2", "classid", "10:80",\
198		 "htb", "rate", "90000kbit", "ceil", "90000kbit", "prio", "1");
199
200	eval("tc", "qdisc", "add", "dev", net_name, "parent", "10:80", "handle", "180:", "pfifo");
201
202// 2009.10 James. {
203	/*eval("tc", "filter", "add", "dev", net_name, "parent", "10:", "protocol", "ip", "prio", "1" ,\
204		"u32", "match", "ip", "dst", lan_ipaddr, "flowid", "10:80");//*/
205	eval("tc", "filter", "add", "dev", net_name, "parent", "10:", "protocol", "ip", "prio", "1",\
206			"handle", "80", "fw", "classid", "10:80");
207// 2009.10 James. }
208#endif
209
210	/*Decide all the max/min=qos_ubw/qos_ubw bandwidth for each classes */
211	ubw = atoi(nvram_get("qos_ubw"));
212	ubw=0.85*ubw;
213	sprintf(qos_ubw, "%d%s", ubw, "kbit");
214	sprintf(qos_min_ubw,"1bps");
215
216	/* Add class for global settings / user specify / server services */
217	/* Add root class 10:1 and BW = qos_ubw */
218	eval("tc", "class", "add", "dev", net_name, "parent", "10:", "classid", "10:1",\
219		 "htb", "rate", qos_ubw, "ceil", qos_ubw);
220
221	// Add class for GAME or VOIP
222	if(nvram_match("qos_pshack_prio", "1")||nvram_match("qos_tos_prio", "1")) {
223		tc_class_global(net_name, "10", qos_min_ubw, qos_ubw, "2");
224		flag |= 0x01;
225	}
226
227	// Add class for Application
228	if(nvram_match("qos_shortpkt_prio", "1")) {
229		tc_class_global(net_name, "20", qos_min_ubw, qos_ubw, "3");
230
231#ifdef GPQOS
232		//for download of WL500gpv2
233		eval("tc", "class", "add", "dev", net_name, "parent", "10:2", "classid", "10:70",\
234		 	"htb", "rate", "90000kbit", "ceil", "90000kbit", "prio", "8" );
235		eval("tc", "qdisc", "add", "dev", net_name, "parent", "10:70", "handle", "170:", "pfifo");
236		eval("tc", "filter", "add", "dev", net_name, "parent", "10:", "protocol", "ip", "prio", "8", \
237		 	"handle", "70", "fw", "classid", "10:70");
238
239// 2009.10 James. {
240		/*eval("tc", "filter", "del", "dev", net_name, "parent", "10:", "protocol", "ip", "prio", "1" ,\
241			"u32", "match", "ip", "dst", lan_ipaddr, "flowid", "10:80");
242		 eval("tc", "filter", "add", "dev", net_name, "parent", "10:", "protocol", "ip", "prio", "1",\
243			"handle", "80", "fw", "classid", "10:80");//*/
244// 2009.10 James. }
245
246		if(atoi(nvram_get("qos_ubw"))>640)
247			sprintf(qos_down,"1Mbit");
248		else
249			sprintf(qos_down,"256kbit");
250
251		eval("tc", "class", "add", "dev", net_name, "parent", "10:2", "classid", "10:90",\
252		 	"htb", "rate", qos_down, "ceil", qos_down, "prio", "9" );
253		eval("tc", "qdisc", "add", "dev", net_name, "parent", "10:90", "handle", "190:", "pfifo");
254		eval("tc", "filter", "add", "dev", net_name, "parent", "10:", "protocol", "ip", "prio", "9", \
255		 	"handle", "90", "fw", "classid", "10:90");
256#else
257		// for download of WL500W
258		sprintf(net_down_name,"br0");
259		sprintf(qos_down_ubw, "100000kbit");
260		eval ("tc","qdisc","del", "dev", net_down_name,"root","2>/dev/null");
261		eval("tc","qdisc","add", "dev", net_down_name, "root", "handle", "10:",\
262		 	"htb", "default", "70");
263		eval("tc",  "class", "add", "dev", net_down_name, "parent", "10:", "classid", "10:1",\
264		 	"htb", "rate", qos_down_ubw, "ceil", qos_down_ubw);
265
266		if(atoi(nvram_get("qos_ubw"))>640)
267			sprintf(qos_down,"1Mbit");
268		else
269			sprintf(qos_down,"256kbit");
270
271		tc_class_global(net_down_name, "70", qos_min_ubw, qos_down_ubw, "8");
272		tc_class_global(net_down_name, "80", qos_min_ubw, qos_down_ubw, "1");
273		tc_class_global(net_down_name, "90", qos_min_ubw, qos_down, "9");
274#endif
275
276		//Add iptables rule of Applications
277		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 80 -j MARK --set-mark 20\n");
278		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 80 -j RETURN\n");
279		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 8080 -j MARK --set-mark 20\n");
280		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 8080 -j RETURN\n");
281		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 443 -j MARK --set-mark 20\n");
282		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 443 -j RETURN\n");
283		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 25 -j MARK --set-mark 20\n");
284		fprintf(fp, "-A POSTROUTING -p tcp -m tcp --dport 25 -j RETURN\n");
285	#if 0
286		fprintf(fp, "-A POSTROUTING -p udp --dport 5060 -j MARK --set-mark 20\n");
287		fprintf(fp, "-A POSTROUTING -p udp --dport 5060 -j RETURN\n");
288		fprintf(fp, "-A POSTROUTING -p udp --dport 6000 -j MARK --set-mark 20\n");
289		fprintf(fp, "-A POSTROUTING -p udp --dport 6000 -j RETURN\n");
290		fprintf(fp, "-A POSTROUTING -p tcp --dport 32000 -j MARK --set-mark 20\n");
291		fprintf(fp, "-A POSTROUTING -p tcp --dport 32000 -j RETURN\n");
292		fprintf(fp, "-A POSTROUTING -p udp --dport 32000 -j MARK --set-mark 20\n");
293		fprintf(fp, "-A POSTROUTING -p udp --dport 32000 -j RETURN\n");
294		fprintf(fp, "-A POSTROUTING -p tcp --dport 32010 -j MARK --set-mark 20\n");
295		fprintf(fp, "-A POSTROUTING -p tcp --dport 32010 -j RETURN\n");
296		fprintf(fp, "-A POSTROUTING -p udp -m mport --dport 16384:16583 -j MARK --set-mark 20\n");
297		fprintf(fp, "-A POSTROUTING -p udp -m mport --dport 16384:16583 -j RETURN\n");
298	#endif
299	}
300
301	// Add class for services such as ftp on router 10:30 priority 4
302	if (nvram_match("qos_service_enable", "1")) {
303		tc_class_global(net_name, "30", qos_min_ubw, qos_ubw, "4");
304
305		//Add iptables rule of ftp
306		fprintf(fp, "-A POSTROUTING -m helper --helper ftp -j MARK --set-mark 30\n");
307		fprintf(fp, "-A POSTROUTING -m helper --helper ftp -j RETURN\n");
308	}
309
310	/* Add class for user specify, 10:20(high), 10:40(middle), 10:60(low)*/
311	if (nvram_match("qos_userspec_app","1")) {
312		for(idx_class=0; idx_class < rulenum; idx_class++) {
313			/*tc_class(net_name, num_conv(idx_class),\
314				 qos_userspec_ubw, qos_other_max, Ch_conv("qos_prio_x", idx_class));*/
315			switch(atoi(Ch_conv("qos_prio_x", idx_class))) {
316				case 1:
317					if((flag & 0x01)==0) {
318						tc_class_global(net_name, "10", qos_min_ubw, qos_ubw, "2");
319						flag |= 0x01;
320					}
321					break;
322				case 4:
323					if((flag & 0x02)==0) {
324						tc_class_global(net_name, "40", qos_min_ubw, qos_ubw, "5");
325						flag |= 0x02;
326					}
327					break;
328				case 6:
329					if((flag & 0x04)==0) {
330						tc_class_global(net_name, "60", qos_min_ubw, qos_ubw, "7");
331						flag |= 0x04;
332					}
333					break;
334			}
335
336			tc_filter(Ch_conv("qos_ip_x", idx_class), Ch_conv("qos_port_x", idx_class), atoi(Ch_conv("qos_prio_x", idx_class)));
337
338		}
339	}
340
341	/*Add the default class 10:10 */
342	tc_class_global(net_name, "50", qos_min_ubw, qos_ubw, "6");
343
344QOS_END:
345	/*write "COMMIT" to /tmp/mangle_rules to end after writing all rules*/
346	fprintf(fp, "COMMIT\n\n");
347	fclose(fp);
348
349	/*recover all iptables rules*/
350	eval("iptables-restore", "/tmp/mangle_rules");
351}
352#endif
353