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