1/* 2 3 ASUS features: 4 - traditional qos 5 - bandwidth limiter 6 7 Copyright (C) ASUSTek. Computer Inc. 8 9*/ 10#include "rc.h" 11#include <arpa/inet.h> 12#include <sys/socket.h> 13 14static const char *qosfn = "/tmp/qos"; 15static const char *mangle_fn = "/tmp/mangle_rules"; 16#ifdef RTCONFIG_IPV6 17static const char *mangle_fn_ipv6 = "/tmp/mangle_rules_ipv6"; 18#endif 19 20int etable_flag = 0; 21int manual_return = 0; 22 23// FindMask : 24// 1. sourceStr : replace "*'" to "0" 25// 2. matchStr : here is "*" 26// 3. replaceStr : here is "0" 27// 4. Mask : find rule's submask 28static int FindMask(char *sourceStr, char *matchStr, char *replaceStr, char *Mask){ 29 char newStr[40]; 30 int strLen; 31 int count = 0; 32 33 char *FindPos = strstr(sourceStr, matchStr); 34 if((!FindPos) || (!matchStr)) return -1; 35 36 while(FindPos != NULL){ 37 count++; 38 //fprintf(stderr,"[FindMask] FindPos=%s, strLen=%d, count=%d, sourceStr=%s\n", FindPos, strLen, count, sourceStr); // tmp test 39 memset(newStr, 0, sizeof(newStr)); 40 strLen = FindPos - sourceStr; 41 strncpy(newStr, sourceStr, strLen); 42 strcat(newStr, replaceStr); 43 strcat(newStr, FindPos + strlen(matchStr)); 44 strcpy(sourceStr, newStr); 45 46 FindPos = strstr(sourceStr, matchStr); 47 } 48 49 switch(count){ 50 case 1: 51 strcpy(Mask, "255.255.255.0"); 52 break; 53 case 2: 54 strcpy(Mask, "255.255.0.0"); 55 break; 56 case 3: 57 strcpy(Mask, "255.0.0.0"); 58 break; 59 case 4: 60 strcpy(Mask, "0.0.0.0"); 61 break; 62 default: 63 strcpy(Mask, "255.255.255.255"); 64 break; 65 } 66 67 //fprintf(stderr,"[FindMask] count=%d, Mask=%s\n", count, Mask); // tmp test 68 return 0; 69} 70 71static unsigned calc(unsigned bw, unsigned pct) 72{ 73 unsigned n = ((unsigned long)bw * pct) / 100; 74 return (n < 2) ? 2 : n; 75} 76 77#ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan 78void del_EbtablesRules(void) 79{ 80 /* Flush all rules in nat table of ebtable*/ 81 eval("ebtables", "-t", "nat", "-F"); 82 etable_flag = 0; 83} 84 85void add_EbtablesRules(void) 86{ 87 if(etable_flag == 1) return; 88 char *nv, *p, *g; 89 nv = g = strdup(nvram_safe_get("wl_ifnames")); 90 if(nv){ 91 while ((p = strsep(&g, " ")) != NULL){ 92 //fprintf(stderr, "%s: g=%s, p=%s\n", __FUNCTION__, g, p); //tmp test 93 eval("ebtables", "-t", "nat", "-A", "PREROUTING", "-i", p, "-j", "mark", "--mark-or", "6", "--mark-target", "ACCEPT"); 94 eval("ebtables", "-t", "nat", "-A", "POSTROUTING", "-o", p, "-j", "mark", "--mark-or", "6", "--mark-target", "ACCEPT"); 95 } 96 free(nv); 97 } 98 99 // for MultiSSID 100 int UnitNum = 2; // wl0.x, wl1.x 101 int GuestNum = 3; // wlx.0, wlx.1, wlx.2 102 char mssid_if[32]; 103 char mssid_enable[32]; 104 int i, j; 105 for( i = 0; i < UnitNum; i++){ 106 for( j = 1; j <= GuestNum; j++ ){ 107 snprintf(mssid_if, sizeof(mssid_if), "wl%d.%d", i, j); 108 snprintf(mssid_enable, sizeof(mssid_enable), "%s_bss_enabled", mssid_if); 109 //fprintf(stderr, "%s: mssid_enable=%s\n", __FUNCTION__, mssid_enable); //tmp test 110 if(!strcmp(nvram_safe_get(mssid_enable), "1")){ 111 eval("ebtables", "-t", "nat", "-A", "PREROUTING", "-i", mssid_if, "-j", "mark", "--mark-or", "6", "--mark-target", "ACCEPT"); 112 eval("ebtables", "-t", "nat", "-A", "POSTROUTING", "-o", mssid_if, "-j", "mark", "--mark-or", "6", "--mark-target", "ACCEPT"); 113 } 114 } 115 } 116 117 etable_flag = 1; 118} 119#endif 120 121void del_iQosRules(void) 122{ 123#ifdef CLS_ACT 124 eval("ip", "link", "set", "imq0", "down"); 125#endif 126 127#ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan 128 del_EbtablesRules(); // flush ebtables nat table 129#endif 130 131 /* Flush all rules in mangle table */ 132 eval("iptables", "-t", "mangle", "-F"); 133#ifdef RTCONFIG_IPV6 134 eval("ip6tables", "-t", "mangle", "-F"); 135#endif 136} 137 138static int add_qos_rules(char *pcWANIF) 139{ 140 FILE *fn; 141#ifdef RTCONFIG_IPV6 142 FILE *fn_ipv6 = NULL; 143#endif 144 char *buf; 145 char *g; 146 char *p; 147 char *desc, *addr, *port, *prio, *transferred, *proto; 148 int class_num; 149 int down_class_num=6; // for download class_num = 0x6 / 0x106 150 int i, inuse; 151 char q_inuse[32]; // for inuse 152 char dport[192], saddr_1[192], saddr_2[192], proto_1[8], proto_2[8],conn[256], end[256], end2[256]; 153 int method; 154 int gum; 155 int sticky_enable; 156 const char *chain; 157 int v4v6_ok; 158 159 if((fn = fopen(mangle_fn, "w")) == NULL) return -2; 160#ifdef RTCONFIG_IPV6 161 if(ipv6_enabled() && (fn_ipv6 = fopen(mangle_fn_ipv6, "w")) == NULL){ 162 fclose(fn); 163 return -3; 164 } 165#endif 166 167 inuse = sticky_enable = 0; 168 169 if(get_model()==MODEL_RTAC56U || get_model()==MODEL_RTAC56S || get_model()==MODEL_RTAC68U || 170 get_model()==MODEL_DSLAC68U || get_model()==MODEL_RTAC87U || get_model()==MODEL_RTAC3200 || 171 get_model()==MODEL_RTAC88U || get_model()==MODEL_RTAC3100 || get_model()==MODEL_RTAC5300 || get_model()==MODEL_RTAC5300R || 172 get_model()==MODEL_RTAC1200G || get_model()==MODEL_RTAC1200GP) 173 manual_return = 1; 174 175 if(nvram_match("qos_sticky", "0")) 176 sticky_enable = 1; 177 178 del_iQosRules(); // flush all rules in mangle table 179 180#ifdef CLS_ACT 181 eval("ip", "link", "set", "imq0", "up"); 182#endif 183 fprintf(stderr, "[qos] iptables START\n"); 184 185 fprintf(fn, 186 "*mangle\n" 187 ":PREROUTING ACCEPT [0:0]\n" 188 ":OUTPUT ACCEPT [0:0]\n" 189 ":QOSO - [0:0]\n" 190 "-A QOSO -j CONNMARK --restore-mark --mask 0x7\n" 191 "-A QOSO -m connmark ! --mark 0/0xff00 -j RETURN\n" 192 ); 193#ifdef RTCONFIG_IPV6 194 if (fn_ipv6 && ipv6_enabled()) 195 fprintf(fn_ipv6, 196 "*mangle\n" 197 ":PREROUTING ACCEPT [0:0]\n" 198 ":OUTPUT ACCEPT [0:0]\n" 199 ":QOSO - [0:0]\n" 200 "-A QOSO -j CONNMARK --restore-mark --mask 0x7\n" 201 "-A QOSO -m connmark ! --mark 0/0xff00 -j RETURN\n" 202 ); 203#endif 204 g = buf = strdup(nvram_safe_get("qos_rulelist")); 205 while (g) { 206 207 /* ASUSWRT 208 qos_rulelist : 209 desc>addr>port>proto>transferred>prio 210 211 addr : (source) IP or MAC or IP-range 212 port : dest port 213 proto : tcp, udp, tcp/udp, any , (icmp, igmp) 214 transferred : min:max 215 prio : 0-4, 0 is the highest 216 */ 217 218 if ((p = strsep(&g, "<")) == NULL) break; 219 if((vstrsep(p, ">", &desc, &addr, &port, &proto, &transferred, &prio)) != 6) continue; 220 class_num = atoi(prio); 221 if ((class_num < 0) || (class_num > 4)) continue; 222 223 i = 1 << class_num; 224 ++class_num; 225 226 //if (method == 1) class_num |= 0x200; 227 if ((inuse & i) == 0) { 228 inuse |= i; 229 fprintf(stderr, "[qos] iptable creates, inuse=%d\n", inuse); 230 } 231 232 v4v6_ok = IPT_V4; 233#ifdef RTCONFIG_IPV6 234 if (fn_ipv6 && ipv6_enabled()) 235 v4v6_ok |= IPT_V6; 236#endif 237 238 /* Beginning of the Rule */ 239 /* 240 if transferred != NULL, class_num must bt 0x1~0x6, not 0x101~0x106 241 0x1~0x6 : keep tracing this connection. 242 0x101~0x106 : connection will be considered as marked connection, won't detect again. 243 */ 244#if 0 245 if(strcmp(transferred, "") != 0 ) 246 method = 1; 247 else 248 method = nvram_get_int("qos_method"); // strict rule ordering 249 gum = (method == 0) ? 0x100 : 0; 250#else 251 method = 1; 252 gum = 0; 253#endif 254 class_num |= gum; 255 down_class_num |= gum; // for download 256 257 chain = "QOSO"; // chain name 258 sprintf(end , " -j CONNMARK --set-return 0x%x/0x7\n", class_num); // CONNMARK string 259 sprintf(end2, " -j RETURN\n"); 260 261 /*************************************************/ 262 /* addr */ 263 /* src mac or src ip or IP range */ 264 /*************************************************/ 265 char tmp[20], addr_t[40]; 266 char *tmp_addr, *q_ip, *q_mac; 267 268 memset(saddr_1, 0, sizeof(saddr_1)); 269 memset(saddr_2, 0, sizeof(saddr_2)); 270 271 memset(tmp, 0, sizeof(tmp)); 272 sprintf(tmp, "%s", addr); 273 tmp_addr = tmp; 274 q_ip = strsep(&tmp_addr, ":"); 275 q_mac = tmp_addr; 276 277 memset(addr_t, 0, sizeof(addr_t)); 278 sprintf(addr_t, "%s", addr); 279 280 // step1: check contain '-' or not, if yes, IP-range, ex. 192.168.1.10-192.168.1.100 281 // step2: check addr is NULL 282 // step3: check IP or MAC 283 // step4: check IP contain '*' or not, if yes, IP-range 284 // step5: check DUT's LAN IP shouldn't inside IP-range 285 286 // step1: check contain '-' or not, if yes, IP-range 287 if(strchr(addr_t, '-') == NULL){ 288 // step2: check addr is NULL 289 if(!strcmp(addr_t, "")){ 290 sprintf(saddr_1, "%s", addr_t); // NULL 291 } 292 else{ // step2 293 // step3: check IP or MAC 294 if (q_mac == NULL){ 295 // step4: check IP contain '*' or not, if yes, IP-range 296 if(strchr(q_ip, '*') != NULL){ 297 char *rule; 298 char Mask[40]; 299 struct in_addr range_A, range_B, range_C; 300 301 memset(Mask, 0, sizeof(Mask)); 302 rule = strdup(addr_t); 303 FindMask(rule, "*", "0", Mask); // find submask and replace "*" to "0" 304 memset(addr_t, 0, sizeof(addr_t)); 305 sprintf(addr_t, "%s", rule); // copy rule to addr_t for v4v6_ok 306 307 unsigned int ip = inet_addr(rule); // covert rule's IP into binary form 308 unsigned int nm = inet_addr(Mask); // covert submask into binary form 309 unsigned int gw = inet_addr(nvram_safe_get("lan_ipaddr")); // covert DUT's LAN IP into binary form 310 unsigned int gw_t = htonl(gw); 311 312 range_A.s_addr = ntohl(gw_t - 1); 313 range_B.s_addr = ntohl(gw_t + 1); 314 range_C.s_addr = ip | ~nm; 315 316 //fprintf(stderr, "[addr] addr_t=%s, rule/Mask=%s/%s, ip/nm/gw=%x/%x/%x\n", addr_t, rule, Mask, ip, nm, gw); // tmp test 317 318 // step5: check DUT's LAN IP shouldn't inside IP-range 319 // DUT's LAN IP inside IP-range 320 if( (ip & nm) == (gw & nm)){ 321 //fprintf(stderr, "[addr] %x/%x/%x/%x/%s matched\n", ip_t, nm_t, gw_t, range_B.s_addr, inet_ntoa(range_B)); // tmp test 322 char range_B_addr[40]; 323 sprintf(range_B_addr, "%s", inet_ntoa(range_B)); 324 325 sprintf(saddr_1, "-m iprange --src-range %s-%s", rule, inet_ntoa(range_A)); // IP-range 326 sprintf(saddr_2, "-m iprange --src-range %s-%s", range_B_addr, inet_ntoa(range_C)); // IP-range 327 } 328 else{ 329 sprintf(saddr_1, "-m iprange --src-range %s-%s", rule, inet_ntoa(range_C)); // IP-range 330 } 331 332 free(rule); 333 } 334 else{ // step4 335 sprintf(saddr_1, "-s %s", addr_t); // IP 336 } 337 338 v4v6_ok &= ipt_addr_compact(addr_t, v4v6_ok, (v4v6_ok==IPT_V4)); 339 if (!v4v6_ok) continue; 340 } 341 else{ // step3 342 sprintf(saddr_1, "-m mac --mac-source %s", addr_t); // MAC 343 } 344 } 345 } 346 else{ // step1 347 sprintf(saddr_1, "-m iprange --src-range %s", addr_t); // IP-range 348 } 349 //fprintf(stderr, "[qos] tmp=%s, ip=%s, mac=%s, addr=%s, addr_t=%s, saddr_1=%s, saddr_2=%s\n", tmp, q_ip, q_mac, addr, addr_t, saddr_1, saddr_2); // tmp test 350 351 /*************************************************/ 352 /* port */ 353 /* single port or multi-ports */ 354 /*************************************************/ 355 char *tmp_port, *q_port, *q_leave; 356 357 sprintf(tmp, "%s", port); 358 tmp_port = tmp; 359 q_port = strsep(&tmp_port, ","); 360 q_leave = tmp_port; 361 362 if(strcmp(port, "") == 0 ){ 363 sprintf(dport, "%s", ""); 364 } 365 else{ 366 if(q_leave != NULL) 367 sprintf(dport, "-m multiport --dport %s", port); // multi port 368 else 369 sprintf(dport, "--dport %s", port); // single port 370 } 371 //fprintf(stderr, "[qos] tmp=%s, q_port=%s, q_leave=%s, port=%s\n", tmp, q_port, q_leave, port ); // tmp test 372 373 /*************************************************/ 374 /* transferred */ 375 /* --connbytes min:max */ 376 /* --connbytes-dir (original/reply/both) */ 377 /* --connbytes-mode (packets/bytes/avgpkt) */ 378 /*************************************************/ 379 char *tmp_trans, *q_min, *q_max; 380 long min, max ; 381 382 sprintf(tmp, "%s", transferred); 383 tmp_trans = tmp; 384 q_min = strsep(&tmp_trans, "~"); 385 q_max = tmp_trans; 386 387 if (strcmp(transferred,"") == 0){ 388 sprintf(conn, "%s", ""); 389 } 390 else{ 391 sprintf(tmp, "%s", q_min); 392 min = atol(tmp); 393 394 if(strcmp(q_max,"") == 0) // q_max == NULL 395 sprintf(conn, "-m connbytes --connbytes %ld:%s --connbytes-dir both --connbytes-mode bytes", min*1024, q_max); 396 else{// q_max != NULL 397 sprintf(tmp, "%s", q_max); 398 max = atol(tmp); 399 sprintf(conn, "-m connbytes --connbytes %ld:%ld --connbytes-dir both --connbytes-mode bytes", min*1024, max*1024-1); 400 } 401 } 402 //fprintf(stderr, "[qos] tmp=%s, transferred=%s, min=%ld, max=%ld, q_max=%s, conn=%s\n", tmp, transferred, min*1024, max*1024-1, q_max, conn); // tmp test 403 404 /*************************************************/ 405 /* proto */ 406 /* tcp, udp, tcp/udp, any, (icmp, igmp) */ 407 /*************************************************/ 408 memset(proto_1, 0, sizeof(proto_1)); 409 memset(proto_2, 0, sizeof(proto_2)); 410 if(!strcmp(proto, "tcp")) 411 { 412 sprintf(proto_1, "-p tcp"); 413 sprintf(proto_2, "NO"); 414 } 415 else if(!strcmp(proto, "udp")) 416 { 417 sprintf(proto_1, "-p udp"); 418 sprintf(proto_2, "NO"); 419 } 420 else if(!strcmp(proto, "any")) 421 { 422 sprintf(proto_1, "%s", ""); 423 sprintf(proto_2, "NO"); 424 } 425 else if(!strcmp(proto, "tcp/udp")) 426 { 427 sprintf(proto_1, "-p tcp"); 428 sprintf(proto_2, "-p udp"); 429 } 430 else{ 431 sprintf(proto_1, "NO"); 432 sprintf(proto_2, "NO"); 433 } 434 //fprintf(stderr, "[qos] proto_1=%s, proto_2=%s, proto=%s\n", proto_1, proto_2, proto); // tmp test 435 436 /*******************************************************************/ 437 /* */ 438 /* build final rule for check proto_1, proto_2, saddr_1, saddr_2 */ 439 /* */ 440 /*******************************************************************/ 441 // step1. check proto != "NO" 442 // step2. if proto = any, no proto / dport 443 // step3. check saddr for ip-range; saddr_1 could be empty, dport only 444 445 if (v4v6_ok & IPT_V4){ 446 // step1. check proto != "NO" 447 if(strcmp(proto_1, "NO")){ 448 // step2. if proto = any, no proto / dport 449 if(strcmp(proto_1, "")){ 450 // step3. check saddr for ip-range;saddr_1 could be empty, dport only 451 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end); 452 if(manual_return) 453 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end2); 454 455 if(strcmp(saddr_2, "")){ 456 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end); 457 if(manual_return) 458 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end2); 459 } 460 } 461 else{ 462 fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end); 463 if(manual_return) 464 fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end2); 465 466 if(strcmp(saddr_2, "")){ 467 fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end); 468 if(manual_return) 469 fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end2); 470 } 471 } 472 } 473 474 // step1. check proto != "NO" 475 if(strcmp(proto_2, "NO")){ 476 // step2. if proto = any, no proto / dport 477 if(strcmp(proto_2, "")){ 478 // step3. check saddr for ip-range;saddr_1 could be empty, dport only 479 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end); 480 if(manual_return) 481 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end2); 482 483 if(strcmp(saddr_2, "")){ 484 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end); 485 if(manual_return) 486 fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end2); 487 } 488 } 489 else{ 490 fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end); 491 if(manual_return) 492 fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end2); 493 494 if(strcmp(saddr_2, "")){ 495 fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end); 496 if(manual_return) 497 fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end2); 498 } 499 } 500 } 501 } 502 503#ifdef RTCONFIG_IPV6 504 if (fn_ipv6 && ipv6_enabled() && (v4v6_ok & IPT_V6)){ 505 // step1. check proto != "NO" 506 if(strcmp(proto_1, "NO")){ 507 // step2. if proto = any, no proto / dport 508 if(strcmp(proto_1, "")){ 509 // step3. check saddr for ip-range;saddr_1 could be empty, dport only 510 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end); 511 if(manual_return) 512 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end2); 513 514 if(strcmp(saddr_2, "")){ 515 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end); 516 if(manual_return) 517 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end2); 518 } 519 } 520 else{ 521 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end); 522 if(manual_return) 523 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end2); 524 525 if(strcmp(saddr_2, "")){ 526 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end); 527 if(manual_return) 528 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end2); 529 } 530 } 531 } 532 533 // step1. check proto != "NO" 534 if(strcmp(proto_2, "NO")){ 535 // step2. if proto = any, no proto / dport 536 if(strcmp(proto_2, "")){ 537 // step3. check saddr for ip-range;saddr_1 could be empty, dport only 538 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end); 539 if(manual_return) 540 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end2); 541 542 if(strcmp(saddr_2, "")){ 543 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end); 544 if(manual_return) 545 fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end2); 546 } 547 } 548 else{ 549 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end); 550 if(manual_return) 551 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end2); 552 if(strcmp(saddr_2, "")){ 553 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end); 554 if(manual_return) 555 fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end2); 556 } 557 } 558 } 559 } 560#endif 561 } 562 free(buf); 563 564 /* lan_addr for iptables use (LAN download) */ 565 char *a, *b, *c, *d; 566 char lan_addr[20]; 567 g = buf = strdup(nvram_safe_get("lan_ipaddr")); 568 if((vstrsep(g, ".", &a, &b, &c, &d)) != 4){ 569 fprintf(stderr,"[qos] lan_ipaddr doesn't exist!!\n"); 570 } 571 else{ 572 sprintf(lan_addr, "%s.%s.%s.0/24", a, b, c); 573 fprintf(stderr,"[qos] lan_addr=%s\n", lan_addr); 574 } 575 free(buf); 576 577 //fprintf(stderr, "[qos] down_class_num=%x\n", down_class_num); 578 579 /* The default class */ 580 i = nvram_get_int("qos_default"); 581 if ((i < 0) || (i > 4)) i = 3; // "lowest" 582 class_num = i + 1; 583 584#ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan 585 if(strncmp(pcWANIF, "ppp", 3)==0){ 586 // ppp related interface doesn't need physdev 587 // do nothing 588 } 589 else{ 590 /* for WLAN to LAN bridge packet */ 591 // ebtables : identify bridge packet 592 add_EbtablesRules(); 593 594 // for multicast 595 fprintf(fn, "-A QOSO -d 224.0.0.0/4 -j CONNMARK --set-return 0x%x/0x7\n", down_class_num); 596 if(manual_return) 597 fprintf(fn , "-A QOSO -d 224.0.0.0/4 -j RETURN\n"); 598 // for download (LAN or wireless) 599 fprintf(fn, "-A QOSO -d %s -j CONNMARK --set-return 0x%x/0x7\n", lan_addr, down_class_num); 600 if(manual_return) 601 fprintf(fn , "-A QOSO -d %s -j RETURN\n", lan_addr); 602/* Requires bridge netfilter, but slows down and breaks EMF/IGS IGMP IPTV Snooping 603 // for WLAN to LAN bridge issue 604 fprintf(fn, "-A POSTROUTING -d %s -m physdev --physdev-is-in -j CONNMARK --set-return 0x6/0x7\n", lan_addr); 605*/ 606 // for download, interface br0 607 fprintf(fn, "-A POSTROUTING -o br0 -j QOSO\n"); 608 } 609#endif 610 fprintf(fn, 611 "-A QOSO -j CONNMARK --set-return 0x%x/0x7\n" 612 "-A FORWARD -o %s -j QOSO\n" 613 "-A OUTPUT -o %s -j QOSO\n", 614 class_num, pcWANIF, pcWANIF); 615 if(manual_return) 616 fprintf(fn , "-A QOSO -j RETURN\n"); 617 618#ifdef RTCONFIG_IPV6 619 if (fn_ipv6 && ipv6_enabled() && *wan6face) { 620#ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan 621 if(strncmp(wan6face, "ppp", 3)==0){ 622 // ppp related interface doesn't need physdev 623 // do nothing 624 } 625 else{ 626 /* for WLAN to LAN bridge packet */ 627 // ebtables : identify bridge packet 628 add_EbtablesRules(); 629 630 // for multicast 631 fprintf(fn_ipv6, "-A QOSO -d 224.0.0.0/4 -j CONNMARK --set-return 0x%x/0x7\n", down_class_num); 632 if(manual_return) 633 fprintf(fn_ipv6, "-A QOSO -d 224.0.0.0/4 -j RETURN\n"); 634 // for download (LAN or wireless) 635 fprintf(fn_ipv6, "-A QOSO -d %s -j CONNMARK --set-return 0x%x/0x7\n", lan_addr, down_class_num); 636 if(manual_return) 637 fprintf(fn_ipv6, "-A QOSO -d %s -j RETURN\n", lan_addr); 638/* Requires bridge netfilter, but slows down and breaks EMF/IGS IGMP IPTV Snooping 639 // for WLAN to LAN bridge issue 640 fprintf(fn_ipv6, "-A POSTROUTING -d %s -m physdev --physdev-is-in -j CONNMARK --set-return 0x6/0x7\n", lan_addr); 641*/ 642 // for download, interface br0 643 fprintf(fn_ipv6, "-A POSTROUTING -o br0 -j QOSO\n"); 644 } 645#endif 646 fprintf(fn_ipv6, 647 "-A QOSO -j CONNMARK --set-return 0x%x/0x7\n" 648 "-A FORWARD -o %s -j QOSO\n" 649 "-A OUTPUT -o %s -j QOSO\n", 650 class_num, wan6face, wan6face); 651 if(manual_return) 652 fprintf(fn_ipv6, "-A QOSO -j RETURN\n"); 653 } 654#endif 655 656 inuse |= (1 << i) | 1; // default and highest are always built 657 sprintf(q_inuse, "%d", inuse); 658 nvram_set("qos_inuse", q_inuse); 659 fprintf(stderr, "[qos] qos_inuse=%d\n", inuse); 660 661 /* Ingress rules */ 662 g = buf = strdup(nvram_safe_get("qos_irates")); 663 for (i = 0; i < 10; ++i) { 664 if ((!g) || ((p = strsep(&g, ",")) == NULL)) continue; 665 if ((inuse & (1 << i)) == 0) continue; 666 if (atoi(p) > 0) { 667 fprintf(fn, "-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0x7\n", pcWANIF); 668#ifdef CLS_ACT 669 fprintf(fn, "-A PREROUTING -i %s -j IMQ --todev 0\n", pcWANIF); 670#endif 671#ifdef RTCONFIG_IPV6 672 if (fn_ipv6 && ipv6_enabled() && *wan6face) { 673 fprintf(fn_ipv6, "-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0x7\n", wan6face); 674#ifdef CLS_ACT 675 fprintf(fn_ipv6, "-A PREROUTING -i %s -j IMQ --todev 0\n", wan6face); 676#endif 677 } 678#endif 679 break; 680 } 681 } 682 free(buf); 683 684 fprintf(fn, "COMMIT\n"); 685 fclose(fn); 686 chmod(mangle_fn, 0700); 687 eval("iptables-restore", (char*)mangle_fn); 688#ifdef RTCONFIG_IPV6 689 if (fn_ipv6 && ipv6_enabled()) 690 { 691 fprintf(fn_ipv6, "COMMIT\n"); 692 fclose(fn_ipv6); 693 chmod(mangle_fn_ipv6, 0700); 694// eval("ip6tables-restore", (char*)mangle_fn_ipv6); 695 } 696#endif 697 fprintf(stderr, "[qos] iptables DONE!\n"); 698 699 return 0; 700} 701 702 703/*******************************************************************/ 704// The definations of all partations 705// eth0 : WAN 706// 1:1 : upload 707// 1:2 : download (1000000Kbits) 708// 1:10 : highest 709// 1:20 : high 710// 1:30 : middle 711// 1:40 : low (default) 712// 1:50 : lowest 713// 1:60 : ALL Download (WAN to LAN and LAN to LAN) (1000000kbits) 714/*******************************************************************/ 715 716/* Tc */ 717static int start_tqos(void) 718{ 719 int i; 720 char *buf, *g, *p; 721 unsigned int rate; 722 unsigned int ceil; 723 unsigned int ibw, obw, bw; 724 unsigned int mtu; 725 FILE *f; 726 int x; 727 int inuse; 728 char s[256]; 729 int first; 730 char burst_root[32]; 731 char burst_leaf[32]; 732#ifdef CONFIG_BCMWL5 733 char *protocol="802.1q"; 734#endif 735 736 // judge interface by get_wan_ifname 737 // add Qos iptable rules in mangle table, 738 // move it to firewall - mangle_setting 739 // add_iQosRules(get_wan_ifname(wan_primary_ifunit())); // iptables start 740 741 ibw = strtoul(nvram_safe_get("qos_ibw"), NULL, 10); 742 obw = strtoul(nvram_safe_get("qos_obw"), NULL, 10); 743 if(ibw==0||obw==0) return -1; 744 745 if((f = fopen(qosfn, "w")) == NULL) return -2; 746 747 fprintf(stderr, "[qos] tc START!\n"); 748 749 /* qos_burst */ 750 i = nvram_get_int("qos_burst0"); 751 if(i > 0) sprintf(burst_root, "burst %dk", i); 752 else burst_root[0] = 0; 753 i = nvram_get_int("qos_burst1"); 754 755 if(i > 0) sprintf(burst_leaf, "burst %dk", i); 756 else burst_leaf[0] = 0; 757 758 /* Egress OBW -- set the HTB shaper (Classful Qdisc) 759 * the BW is set here for each class 760 */ 761 762 mtu = strtoul(nvram_safe_get("wan_mtu"), NULL, 10); 763 bw = obw; 764 765 /* WAN */ 766 fprintf(f, 767 "#!/bin/sh\n" 768 "#LAN/WAN\n" 769 "I=%s\n" 770 "SFQ=\"sfq perturb 10\"\n" 771 "TQA=\"tc qdisc add dev $I\"\n" 772 "TCA=\"tc class add dev $I\"\n" 773 "TFA=\"tc filter add dev $I\"\n" 774#ifdef CLS_ACT 775 "DLIF=imq0\n" 776 "TQADL=\"tc qdisc add dev $DLIF\"\n" 777 "TCADL=\"tc class add dev $DLIF\"\n" 778 "TFADL=\"tc filter add dev $DLIF\"\n" 779#endif 780 "case \"$1\" in\n" 781 "start)\n" 782 "#LAN/WAN\n" 783 "\ttc qdisc del dev $I root 2>/dev/null\n" 784 "\t$TQA root handle 1: htb default %u\n" 785#ifdef CLS_ACT 786 "\ttc qdisc del dev $DLIF root 2>/dev/null\n" 787 "\t$TQADL root handle 2: htb default %u\n" 788#endif 789 "# upload 1:1\n" 790 "\t$TCA parent 1: classid 1:1 htb rate %ukbit ceil %ukbit %s\n" , 791 get_wan_ifname(wan_primary_ifunit()), // judge WAN interface 792 (nvram_get_int("qos_default") + 1) * 10, 793#ifdef CLS_ACT 794 (nvram_get_int("qos_default") + 1) * 10, 795#endif 796 bw, bw, burst_root); 797 798 /* LAN protocol: 802.1q */ 799#ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan 800 protocol = "802.1q"; 801 fprintf(f, 802 "# download 1:2\n" 803 "\t$TCA parent 1: classid 1:2 htb rate 1000000kbit ceil 1000000kbit burst 10000 cburst 10000\n" 804 "# 1:60 ALL Download for BCM\n" 805 "\t$TCA parent 1:2 classid 1:60 htb rate 1000000kbit ceil 1000000kbit burst 10000 cburst 10000 prio 6\n" 806 "\t$TQA parent 1:60 handle 60: pfifo\n" 807 "\t$TFA parent 1: prio 6 protocol %s handle 6 fw flowid 1:60\n", protocol 808 ); 809#endif 810 811 inuse = nvram_get_int("qos_inuse"); 812 813 g = buf = strdup(nvram_safe_get("qos_orates")); 814 for (i = 0; i < 5; ++i) { // 0~4 , 0:highest, 4:lowest 815 816 if ((!g) || ((p = strsep(&g, ",")) == NULL)) break; 817 818 if ((inuse & (1 << i)) == 0){ 819 fprintf(stderr, "[qos] egress %d doesn't create, inuse=%d\n", i, inuse ); 820 continue; 821 } 822 else 823 fprintf(stderr, "[qos] egress %d creates\n", i); 824 825 if ((sscanf(p, "%u-%u", &rate, &ceil) != 2) || (rate < 1)) continue; 826 827 if (ceil > 0) sprintf(s, "ceil %ukbit ", calc(bw, ceil)); 828 else s[0] = 0; 829 x = (i + 1) * 10; 830 831 fprintf(f, 832 "# egress %d: %u-%u%%\n" 833 "\t$TCA parent 1:1 classid 1:%d htb rate %ukbit %s %s prio %d quantum %u\n" 834 "\t$TQA parent 1:%d handle %d: $SFQ\n" 835 "\t$TFA parent 1: prio %d protocol ip handle %d fw flowid 1:%d\n", 836 i, rate, ceil, 837 x, calc(bw, rate), s, burst_leaf, (i >= 6) ? 7 : (i + 1), mtu, 838 x, x, 839 x, i + 1, x); 840 } 841 free(buf); 842 843 /* 844 10000 = ACK 845 00100 = RST 846 00010 = SYN 847 00001 = FIN 848 */ 849 850 if (nvram_match("qos_ack", "on")) { 851 fprintf(f, 852 "\n" 853 "\t$TFA parent 1: prio 14 protocol ip u32 " 854 "match ip protocol 6 0xff " // TCP 855 "match u8 0x05 0x0f at 0 " // IP header length 856 "match u16 0x0000 0xffc0 at 2 " // total length (0-63) 857 "match u8 0x10 0xff at 33 " // ACK only 858 "flowid 1:10\n"); 859 } 860 if (nvram_match("qos_syn", "on")) { 861 fprintf(f, 862 "\n" 863 "\t$TFA parent 1: prio 15 protocol ip u32 " 864 "match ip protocol 6 0xff " // TCP 865 "match u8 0x05 0x0f at 0 " // IP header length 866 "match u16 0x0000 0xffc0 at 2 " // total length (0-63) 867 "match u8 0x02 0x02 at 33 " // SYN,* 868 "flowid 1:10\n"); 869 } 870 if (nvram_match("qos_fin", "on")) { 871 fprintf(f, 872 "\n" 873 "\t$TFA parent 1: prio 17 protocol ip u32 " 874 "match ip protocol 6 0xff " // TCP 875 "match u8 0x05 0x0f at 0 " // IP header length 876 "match u16 0x0000 0xffc0 at 2 " // total length (0-63) 877 "match u8 0x01 0x01 at 33 " // FIN,* 878 "flowid 1:10\n"); 879 } 880 if (nvram_match("qos_rst", "on")) { 881 fprintf(f, 882 "\n" 883 "\t$TFA parent 1: prio 19 protocol ip u32 " 884 "match ip protocol 6 0xff " // TCP 885 "match u8 0x05 0x0f at 0 " // IP header length 886 "match u16 0x0000 0xffc0 at 2 " // total length (0-63) 887 "match u8 0x04 0x04 at 33 " // RST,* 888 "flowid 1:10\n"); 889 } 890 if (nvram_match("qos_icmp", "on")) { 891 fputs("\n\t$TFA parent 1: prio 13 protocol ip u32 match ip protocol 1 0xff flowid 1:10\n", f); 892 } 893 894 // ingress 895 first = 1; 896 bw = ibw; 897 898 if (bw > 0) { 899 g = buf = strdup(nvram_safe_get("qos_irates")); 900 for (i = 0; i < 5; ++i) { // 0~4 , 0:highest, 4:lowest 901 if ((!g) || ((p = strsep(&g, ",")) == NULL)) break; 902 if ((inuse & (1 << i)) == 0) continue; 903 if ((rate = atoi(p)) < 1) continue; // 0 = off 904 905 if (first) { 906 first = 0; 907 fprintf(f, 908 "\n" 909#if !defined(CLS_ACT) 910 "\ttc qdisc del dev $I ingress 2>/dev/null\n" 911 "\t$TQA handle ffff: ingress\n" 912#endif 913 ); 914 } 915 916 // rate in kb/s 917 unsigned int u = calc(bw, rate); 918 919 // burst rate 920 unsigned int v = u / 2; 921 if (v < 50) v = 50; 922 923#ifdef CLS_ACT 924 x = (i + 1) * 10; 925 fprintf(f, 926 "# ingress %d: %u%%\n" 927 "\t$TCADL parent 2:1 classid 2:%d htb rate %ukbit %s prio %d quantum %u\n" 928 "\t$TQADL parent 2:%d handle %d: $SFQ\n" 929 "\t$TFADL parent 2: prio %d protocol ip handle %d fw flowid 2:%d\n", 930 i, rate, 931 x, calc(bw, rate), burst_leaf, (i >= 6) ? 7 : (i + 1), mtu, 932 x, x, 933 x, i + 1, x); 934#else 935 x = i + 1; 936 fprintf(f, 937 "# ingress %d: %u%%\n" 938 "\t$TFA parent ffff: prio %d protocol ip handle %d" 939 " fw police rate %ukbit burst %ukbit drop flowid ffff:%d\n", 940 i, rate, x, x, u, v, x); 941#endif 942 } 943 free(buf); 944 } 945 946 fputs( 947 "\t;;\n" 948 "stop)\n" 949 "\ttc qdisc del dev $I root 2>/dev/null\n" 950#ifdef CLS_ACT 951 "\ttc qdisc del dev $DLIF root 2>/dev/null\n" 952#else 953 "\ttc qdisc del dev $I ingress 2>/dev/null\n" 954#endif 955 "\t;;\n" 956 "*)\n" 957 "\t#---------- Upload ----------\n" 958 "\ttc -s -d class ls dev $I\n" 959 "\ttc -s -d qdisc ls dev $I\n" 960 "\techo\n" 961#ifdef CLS_ACT 962 "\t#--------- Download ---------\n" 963 "\ttc -s -d class ls dev $DLIF\n" 964 "\ttc -s -d qdisc ls dev $DLIF\n" 965 "\techo\n" 966#endif 967 "esac\n", 968 f); 969 970 fclose(f); 971 chmod(qosfn, 0700); 972 eval((char *)qosfn, "start"); 973 fprintf(stderr,"[qos] tc done!\n"); 974 975 return 0; 976} 977 978 979void stop_iQos(void) 980{ 981 eval((char *)qosfn, "stop"); 982} 983 984#define TYPE_IP 0 985#define TYPE_MAC 1 986#define TYPE_IPRANGE 2 987#define TYPE_GUEST 3 988 989static void address_checker(int *addr_type, char *addr_old, char *addr_new, int len) 990{ 991 char *second, *last_dot; 992 int len_to_minus, len_to_dot; 993 994 // guestnetwork interface 995 if (strstr(addr_old, "wl")){ 996 *addr_type = TYPE_GUEST; 997 strncpy(addr_new, addr_old, len); 998 return; 999 } 1000 1001 second = strchr(addr_old, '-'); 1002 if (second != NULL) 1003 { 1004 *addr_type = TYPE_IPRANGE; 1005 if (strchr(second+1, '.') != NULL){ 1006 // long notation 1007 strncpy(addr_new, addr_old, len); 1008 } 1009 else{ 1010 // short notation 1011 last_dot = strrchr(addr_old, '.'); 1012 len_to_minus = second - addr_old; 1013 len_to_dot = last_dot - addr_old; 1014 strncpy(addr_new, addr_old, len_to_minus+1); 1015 strncpy(addr_new + len_to_minus + 1, addr_new, len_to_dot+1); 1016 strcpy(addr_new + len_to_minus + len_to_dot + 2, second+1); 1017 } 1018 } 1019 else 1020 { 1021 if (strlen(addr_old) == 17) 1022 *addr_type = TYPE_MAC; 1023 else 1024 *addr_type = TYPE_IP; 1025 strncpy(addr_new, addr_old, len); 1026 } 1027} 1028 1029static int add_bandwidth_limiter_rules(char *pcWANIF) 1030{ 1031 FILE *fn = NULL; 1032 char *buf, *g, *p; 1033 char *enable, *addr, *dlc, *upc, *prio; 1034 char lan_addr[32]; 1035 char addr_new[32]; 1036 int addr_type; 1037 char *action = NULL; 1038 1039 if ((fn = fopen(mangle_fn, "w")) == NULL) return -2; 1040 del_iQosRules(); // flush all rules in mangle table 1041 1042 switch (get_model()){ 1043 case MODEL_DSLN55U: 1044 case MODEL_RTN13U: 1045 case MODEL_RTN56U: 1046 action = "CONNMARK --set-return"; 1047 manual_return = 0; 1048 break; 1049 default: 1050 action = "MARK --set-mark"; 1051 manual_return = 1; 1052 break; 1053 } 1054 1055 /* ASUSWRT 1056 qos_bw_rulelist : 1057 enable>addr>DL-Ceil>UL-Ceil>prio 1058 enable : enable or disable this rule 1059 addr : (source) IP or MAC or IP-range or wireless interface(wl0.1, wl0.2, etc.) 1060 DL-Ceil : the max download bandwidth 1061 UL-Ceil : the max upload bandwidth 1062 prio : priority for client 1063 */ 1064 1065 memset(lan_addr, 0, sizeof(lan_addr)); 1066 sprintf(lan_addr, "%s/%s", nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask")); 1067 1068 fprintf(fn, 1069 "*mangle\n" 1070 ":PREROUTING ACCEPT [0:0]\n" 1071 ":OUTPUT ACCEPT [0:0]\n" 1072 ); 1073 1074 // access router : mark 9 1075 fprintf(fn, 1076 "-A POSTROUTING -s %s -d %s -j %s 9\n" 1077 "-A PREROUTING -s %s -d %s -j %s 9\n" 1078 , nvram_safe_get("lan_ipaddr"), lan_addr, action 1079 , lan_addr, nvram_safe_get("lan_ipaddr"), action 1080 ); 1081 1082 if(manual_return){ 1083 fprintf(fn, 1084 "-A POSTROUTING -s %s -d %s -j RETURN\n" 1085 "-A PREROUTING -s %s -d %s -j RETURN\n" 1086 , nvram_safe_get("lan_ipaddr"), lan_addr 1087 , lan_addr, nvram_safe_get("lan_ipaddr") 1088 ); 1089 } 1090 1091 g = buf = strdup(nvram_safe_get("qos_bw_rulelist")); 1092 while (g) { 1093 if ((p = strsep(&g, "<")) == NULL) break; 1094 if ((vstrsep(p, ">", &enable, &addr, &dlc, &upc, &prio)) != 5) continue; 1095 if (!strcmp(enable, "0")) continue; 1096 memset(addr_new, 0, sizeof(addr_new)); 1097 address_checker(&addr_type, addr, addr_new, sizeof(addr_new)); 1098 _dprintf("[BWLIT] %s: addr_type=%d, addr=%s, add_new=%s, lan_addr=%s\n", __FUNCTION__, addr_type, addr, addr_new, lan_addr); 1099 1100 if (addr_type == TYPE_IP){ 1101 fprintf(fn, 1102 "-A POSTROUTING ! -s %s -d %s -j %s %d\n" 1103 "-A PREROUTING -s %s ! -d %s -j %s %d\n" 1104 , lan_addr, addr_new, action, atoi(prio)+10 1105 , addr_new, lan_addr, action, atoi(prio)+10 1106 ); 1107 if(manual_return){ 1108 fprintf(fn, 1109 "-A POSTROUTING ! -s %s -d %s -j RETURN\n" 1110 "-A PREROUTING -s %s ! -d %s -j RETURN\n" 1111 , lan_addr, addr_new, addr_new, lan_addr 1112 ); 1113 } 1114 } 1115 else if (addr_type == TYPE_MAC){ 1116 fprintf(fn, 1117 "-A PREROUTING -m mac --mac-source %s ! -d %s -j %s %d\n" 1118 , addr_new, lan_addr, action, atoi(prio)+10 1119 ); 1120 if(manual_return){ 1121 fprintf(fn, 1122 "-A PREROUTING -m mac --mac-source %s ! -d %s -j RETURN\n" 1123 , addr_new, lan_addr 1124 ); 1125 } 1126 } 1127 else if (addr_type == TYPE_IPRANGE){ 1128 fprintf(fn, 1129 "-A POSTROUTING ! -s %s -m iprange --dst-range %s -j %s %d\n" 1130 "-A PREROUTING -m iprange --src-range %s ! -d %s -j %s %d\n" 1131 , lan_addr, addr_new, action, atoi(prio)+10 1132 , addr_new, lan_addr, action, atoi(prio)+10 1133 ); 1134 if(manual_return){ 1135 fprintf(fn, 1136 "-A POSTROUTING ! -s %s -m iprange --dst-range %s -j RETURN\n" 1137 "-A PREROUTING -m iprange --src-range %s ! -d %s -j RETURN\n" 1138 , lan_addr, addr_new, addr_new, lan_addr 1139 ); 1140 } 1141 } 1142 else if (addr_type == TYPE_GUEST) continue; 1143 } 1144 free(buf); 1145 1146 fprintf(fn, "COMMIT\n"); 1147 fclose(fn); 1148 chmod(mangle_fn, 0700); 1149 eval("iptables-restore", (char*)mangle_fn); 1150 _dprintf("[BWLIT] %s: create rules\n", __FUNCTION__); 1151 1152 return 0; 1153} 1154 1155static int guest; // qdisc root only 3: ~ 12: (9 guestnetwork) 1156 1157static int start_bandwidth_limiter(void) 1158{ 1159 FILE *f = NULL; 1160 char *buf, *g, *p; 1161 char *enable, *addr, *dlc, *upc, *prio; 1162 int class = 0; 1163 int s[6]; // strip mac address 1164 int addr_type; 1165 char addr_new[30]; 1166 1167 // init guest 3: ~ 12: (9 guestnetwork), start number = 3 1168 guest = 3; 1169 1170 if ((f = fopen(qosfn, "w")) == NULL) return -2; 1171 fprintf(f, 1172 "#!/bin/sh\n" 1173 "WAN=%s\n" 1174 "\n" 1175 "case \"$1\" in\n" 1176 "start)\n" 1177 , get_wan_ifname(wan_primary_ifunit()) 1178 ); 1179 1180 /* ASUSWRT 1181 qos_bw_rulelist : 1182 enable>addr>DL-Ceil>UL-Ceil>prio 1183 enable : enable or disable this rule 1184 addr : (source) IP or MAC or IP-range or wireless interface(wl0.1, wl0.2, etc.) 1185 DL-Ceil : the max download bandwidth 1186 UL-Ceil : the max upload bandwidth 1187 prio : priority for client 1188 */ 1189 1190 g = buf = strdup(nvram_safe_get("qos_bw_rulelist")); 1191 1192 // if no qos_bw_rulelist, shouldn't set tc rule 1193 if (strcmp(g, "")) { 1194 fprintf(f, 1195 "tc qdisc del dev $WAN root 2>/dev/null\n" 1196 "tc qdisc del dev $WAN ingress 2>/dev/null\n" 1197 "tc qdisc del dev br0 root 2>/dev/null\n" 1198 "tc qdisc del dev br0 ingress 2>/dev/null\n" 1199 "\n" 1200 "TQAU=\"tc qdisc add dev $WAN\"\n" 1201 "TCAU=\"tc class add dev $WAN\"\n" 1202 "TFAU=\"tc filter add dev $WAN\"\n" 1203 "SFQ=\"sfq perturb 10\"\n" 1204 "TQA=\"tc qdisc add dev br0\"\n" 1205 "TCA=\"tc class add dev br0\"\n" 1206 "TFA=\"tc filter add dev br0\"\n" 1207 "\n" 1208 "$TQA root handle 1: htb\n" 1209 "$TCA parent 1: classid 1:1 htb rate 10240000kbit\n" 1210 "\n" 1211 "$TQAU root handle 2: htb\n" 1212 "$TCAU parent 2: classid 2:1 htb rate 10240000kbit\n" 1213 ); 1214 1215 // access router : mark 9 1216 // default : 10Gbps 1217 fprintf(f, 1218 "\n" 1219 "$TCA parent 1:1 classid 1:9 htb rate 10240000kbit ceil 10240000kbit prio 1\n" 1220 "$TQA parent 1:9 handle 9: $SFQ\n" 1221 "$TFA parent 1: prio 1 protocol ip handle 9 fw flowid 1:9\n" 1222 "\n" 1223 "$TCAU parent 2:1 classid 2:9 htb rate 10240000kbit ceil 10240000kbit prio 1\n" 1224 "$TQAU parent 2:9 handle 9: $SFQ\n" 1225 "$TFAU parent 2: prio 1 protocol ip handle 9 fw flowid 2:9\n" 1226 ); 1227 } 1228 1229 while (g) { 1230 if ((p = strsep(&g, "<")) == NULL) break; 1231 if ((vstrsep(p, ">", &enable, &addr, &dlc, &upc, &prio)) != 5) continue; 1232 if (!strcmp(enable, "0")) continue; 1233 1234 address_checker(&addr_type, addr, addr_new, sizeof(addr_new)); 1235 class = atoi(prio) + 10; 1236 if (addr_type == TYPE_MAC) 1237 { 1238 sscanf(addr_new, "%02X:%02X:%02X:%02X:%02X:%02X",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5]); 1239 fprintf(f, 1240 "\n" 1241 "$TCA parent 1:1 classid 1:%d htb rate %skbit ceil %skbit prio %d\n" 1242 "$TQA parent 1:%d handle %d: $SFQ\n" 1243 "$TFA parent 1: protocol ip prio %d 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:%d" 1244 "\n" 1245 "$TCAU parent 2:1 classid 2:%d htb rate %skbit ceil %skbit prio %d\n" 1246 "$TQAU parent 2:%d handle %d: $SFQ\n" 1247 "$TFAU parent 2: prio %d protocol ip handle %d fw flowid 2:%d\n" 1248 , class, dlc, dlc, class 1249 , class, class 1250 , class, s[2], s[3], s[4], s[5], s[0], s[1], class 1251 , class, upc, upc, class 1252 , class, class 1253 , class, class, class 1254 ); 1255 } 1256 else if (addr_type == TYPE_IP || addr_type == TYPE_IPRANGE) 1257 { 1258 fprintf(f, 1259 "\n" 1260 "$TCA parent 1:1 classid 1:%d htb rate %skbit ceil %skbit prio %d\n" 1261 "$TQA parent 1:%d handle %d: $SFQ\n" 1262 "$TFA parent 1: prio %d protocol ip handle %d fw flowid 1:%d\n" 1263 "\n" 1264 "$TCAU parent 2:1 classid 2:%d htb rate %skbit ceil %skbit prio %d\n" 1265 "$TQAU parent 2:%d handle %d: $SFQ\n" 1266 "$TFAU parent 2: prio %d protocol ip handle %d fw flowid 2:%d\n" 1267 , class, dlc, dlc, class 1268 , class, class 1269 , class, class, class 1270 , class, upc, upc, class 1271 , class, class 1272 , class, class, class 1273 ); 1274 } 1275 else if (addr_type == TYPE_GUEST) 1276 { 1277 // setup guest network's bandwidth limiter 1278 char mssid_mark[4]; 1279 char *wl_if = NULL; 1280 int i, j; 1281 1282 if(sscanf(addr_new, "wl%d.%d", &i, &j) != 2){ 1283 _dprintf("[BWLIT] %s: fail to strip i, j from wlx.x\n", __FUNCTION__); 1284 } 1285 1286 snprintf(mssid_mark, sizeof(mssid_mark), "%d", class); 1287 1288 if(get_model()==MODEL_RTAC87U && (i == 1)){ 1289 if(j == 1) wl_if = "vlan4000"; 1290 if(j == 2) wl_if = "vlan4001"; 1291 if(j == 3) wl_if = "vlan4002"; 1292 } 1293 else{ 1294 wl_if = addr_new; 1295 } 1296 1297 eval("ebtables", "-t", "nat", "-A", "PREROUTING", "-i", wl_if, "-j", "mark", "--set-mark", mssid_mark, "--mark-target", "ACCEPT"); 1298 eval("ebtables", "-t", "nat", "-A", "POSTROUTING", "-o", wl_if, "-j", "mark", "--set-mark", mssid_mark, "--mark-target", "ACCEPT"); 1299 1300 fprintf(f, 1301 "\n" 1302 "tc qdisc del dev %s root 2>/dev/null\n" 1303 "GUEST%d%d=%s\n" 1304 "TQA%d%d=\"tc qdisc add dev $GUEST%d%d\"\n" 1305 "TCA%d%d=\"tc class add dev $GUEST%d%d\"\n" 1306 "TFA%d%d=\"tc filter add dev $GUEST%d%d\"\n" // 5 1307 "\n" 1308 "$TQA%d%d root handle %d: htb\n" 1309 "$TCA%d%d parent %d: classid %d:1 htb rate %skbit\n" // 7 1310 "\n" 1311 "$TCA%d%d parent %d:1 classid %d:%d htb rate 1kbit ceil %skbit prio %d\n" 1312 "$TQA%d%d parent %d:%d handle %d: $SFQ\n" 1313 "$TFA%d%d parent %d: prio %d protocol ip handle %d fw flowid %d:%d\n" // 10 1314 "\n" 1315 "$TCAU parent 2:1 classid 2:%d htb rate 1kbit ceil %skbit prio %d\n" 1316 "$TQAU parent 2:%d handle %d: $SFQ\n" 1317 "$TFAU parent 2: prio %d protocol ip handle %d fw flowid 2:%d\n" // 13 1318 , wl_if 1319 , i, j, wl_if 1320 , i, j, i, j 1321 , i, j, i, j 1322 , i, j, i, j // 5 1323 , i, j, guest 1324 , i, j, guest, guest, dlc //7 1325 , i, j, guest, guest, class, dlc, class 1326 , i, j, guest, class, class 1327 , i, j, guest, class, class, guest, class // 10 1328 , class, upc, class 1329 , class, class 1330 , class, class, class //13 1331 ); 1332 _dprintf("[BWLIT] %s: create %s bandwidth limiter, qdisc=%d, class=%d\n", __FUNCTION__, wl_if, guest, class); 1333 guest++; // add guest 3: ~ 12: (9 guestnetwork) 1334 } 1335 } 1336 free(buf); 1337 1338 fprintf(f, 1339 ";;\n" 1340 "stop)\n" 1341 "tc qdisc del dev $WAN root 2>/dev/null\n" 1342 "tc qdisc del dev $WAN ingress 2>/dev/null\n" 1343 "tc qdisc del dev br0 root 2>/dev/null\n" 1344 "tc qdisc del dev br0 ingress 2>/dev/null\n" 1345 ";;\n" 1346 "*)\n" 1347 "tc -s -d class ls dev $WAN\n" 1348 "tc -s -d class ls dev br0\n" 1349 "esac" 1350 ); 1351 1352 fclose(f); 1353 chmod(qosfn, 0700); 1354 eval((char *)qosfn, "start"); 1355 _dprintf("[BWLIT] %s: create bandwidth limiter\n", __FUNCTION__); 1356 1357 return 0; 1358} 1359 1360int add_iQosRules(char *pcWANIF) 1361{ 1362 int status = 0; 1363 if (pcWANIF == NULL || nvram_get_int("qos_enable") != 1 || nvram_get_int("qos_type") == 1) return -1; 1364 1365 if (nvram_get_int("qos_enable") == 1 && nvram_get_int("qos_type") == 0) 1366 status = add_qos_rules(pcWANIF); 1367 else if (nvram_get_int("qos_enable") == 1 && nvram_get_int("qos_type") == 2) 1368 status = add_bandwidth_limiter_rules(pcWANIF); 1369 1370 if (status < 0) _dprintf("[%s] status = %d\n", __FUNCTION__, status); 1371 1372 return status; 1373} 1374 1375int start_iQos(void) 1376{ 1377 int status = 0; 1378 if (nvram_get_int("qos_enable") != 1 || nvram_get_int("qos_type") == 1) return -1; 1379 1380 if (nvram_get_int("qos_enable") == 1 && nvram_get_int("qos_type") == 0) 1381 status = start_tqos(); 1382 else if (nvram_get_int("qos_enable") == 1 && nvram_get_int("qos_type") == 2) 1383 status = start_bandwidth_limiter(); 1384 1385 if (status < 0) _dprintf("[%s] status = %d\n", __FUNCTION__, status); 1386 1387 return status; 1388} 1389