int add_iQosRules(char *pcWANIF) { FILE *fn; #ifdef RTCONFIG_IPV6 FILE *fn_ipv6; #endif char *buf; char *g; char *p; char *desc, *addr, *port, *prio, *transferred, *proto; int class_num; int down_class_num=6; // for download class_num = 0x6 / 0x106 int proto_num; int i, inuse; char q_inuse[32]; // for inuse char dport[192], saddr[192], conn[256], end[256]; int method; int gum; int sticky_enable; const char *chain; int v4v6_ok; if (pcWANIF == NULL || !nvram_match("qos_enable", "1")) return -1; if ((fn = fopen(mangle_fn, "w")) == NULL) return -2; #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && (fn_ipv6 = fopen(mangle_fn_ipv6, "w")) == NULL) return -3; #endif inuse = sticky_enable = 0; if (nvram_match("qos_sticky", "0")) sticky_enable = 1; del_iQosRules(); // flush all rules in mangle table fprintf(stderr, "[qos] iptables START\n"); fprintf(fn, "*mangle\n" ":PREROUTING ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":QOSO - [0:0]\n" "-A QOSO -j CONNMARK --restore-mark --mask 0xff\n" "-A QOSO -m connmark ! --mark 0/0xff00 -j RETURN\n" ); #ifdef RTCONFIG_IPV6 if (ipv6_enabled()) fprintf(fn_ipv6, "*mangle\n" ":PREROUTING ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":QOSO - [0:0]\n" "-A QOSO -j CONNMARK --restore-mark --mask 0xff\n" "-A QOSO -m connmark ! --mark 0/0xff00 -j RETURN\n" ); #endif g = buf = strdup(nvram_safe_get("qos_rulelist")); while (g) { /* ASUSWRT qos_rulelist : desc>addr>port>proto>transferred>prio addr : source ip or mac port : dest port proto : tcp, udp, tcp/udp, any , (icmp, igmp) transferred : min:max prio : 0-4, 0 is the highest */ if ((p = strsep(&g, "<")) == NULL) break; if((vstrsep(p, ">", &desc, &addr, &port, &proto, &transferred, &prio)) != 6) continue; class_num = atoi(prio); if ((class_num < 0) || (class_num > 4)) continue; i = 1 << class_num; ++class_num; //if (method == 1) class_num |= 0x200; if ((inuse & i) == 0) { inuse |= i; fprintf(stderr, "[qos] iptable creates, inuse=%d\n", inuse); } v4v6_ok = IPT_V4; #ifdef RTCONFIG_IPV6 if (ipv6_enabled()) v4v6_ok |= IPT_V6; #endif /* Beginning of the Rule */ /* if transferred != NULL, class_num must bt 0x1~0x6, not 0x101~0x106 0x1~0x6 : keep tracing this connection. 0x101~0x106 : connection will be considered as marked connection, won't detect again. */ #if 0 if(strcmp(transferred, "") != 0 ) method = 1; else method = atoi(nvram_safe_get("qos_method")); // strict rule ordering gum = (method == 0) ? 0x100 : 0; #else method = 1; gum = 0; #endif class_num |= gum; down_class_num |= gum; // for download chain = "QOSO"; // chain name sprintf(end , " -j CONNMARK --set-return 0x%x/0xFF\n", class_num); // CONNMARK string /*************************************************/ /* addr */ /* src mac or src ip */ /*************************************************/ char tmp[20]; char *tmp_addr, *q_ip, *q_mac; sprintf(tmp, "%s", addr); tmp_addr = tmp; q_ip = strsep(&tmp_addr, ":"); q_mac = tmp_addr; if(strcmp(addr, "") == 0 ) sprintf(saddr, "%s", addr); // src addr else{ if (q_mac == NULL){ sprintf(saddr, "-s %s", addr); // src addr v4v6_ok &= ipt_addr_compact(addr, v4v6_ok, (v4v6_ok==IPT_V4)); if (!v4v6_ok) continue; } else{ sprintf(saddr, "-m mac --mac-source %s", addr); // src mac } } //fprintf(stderr, "[qos] tmp=%s, ip=%s, mac=%s, addr=%s\n", tmp, q_ip, q_mac, addr ); // tmp test /*************************************************/ /* port */ /* single port or multi-ports */ /*************************************************/ char *tmp_port, *q_port, *q_leave; sprintf(tmp, "%s", port); tmp_port = tmp; q_port = strsep(&tmp_port, ","); q_leave = tmp_port; if(strcmp(port, "") == 0 ){ sprintf(dport, ""); } else{ if(q_leave != NULL) sprintf(dport, "-m multiport --dport %s", port); // multi port else sprintf(dport, "--dport %s", port); // single port } //fprintf(stderr, "[qos] tmp=%s, q_port=%s, q_leave=%s, port=%s\n", tmp, q_port, q_leave, port ); // tmp test /*************************************************/ /* transferred */ /* --connbytes min:max */ /* --connbytes-dir (original/reply/both) */ /* --connbytes-mode (packets/bytes/avgpkt) */ /*************************************************/ char *tmp_trans, *q_min, *q_max; long min, max ; sprintf(tmp, "%s", transferred); tmp_trans = tmp; q_min = strsep(&tmp_trans, "~"); q_max = tmp_trans; if (strcmp(transferred,"") == 0){ sprintf(conn, ""); } else{ sprintf(tmp, "%s", q_min); min = atol(tmp); if(strcmp(q_max,"") == 0) // q_max == NULL sprintf(conn, "-m connbytes --connbytes %ld:%s --connbytes-dir both --connbytes-mode bytes", min*1024, q_max); else{// q_max != NULL sprintf(tmp, "%s", q_max); max = atol(tmp); sprintf(conn, "-m connbytes --connbytes %ld:%ld --connbytes-dir both --connbytes-mode bytes", min*1024, max*1024-1); } } //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 /*************************************************/ /* proto */ /* tcp, udp, tcp/udp, any, (icmp, igmp) */ /*************************************************/ if(strcmp(proto, "tcp") == 0 ) { if (v4v6_ok & IPT_V4) fprintf(fn, "-A %s -p %s %s %s %s %s", chain, "tcp", dport, saddr, conn, end); #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && (v4v6_ok & IPT_V6)) fprintf(fn_ipv6, "-A %s -p %s %s %s %s %s", chain, "tcp", dport, saddr, conn, end); #endif } else if(strcmp(proto, "udp") == 0 ) { if (v4v6_ok & IPT_V4) fprintf(fn, "-A %s -p %s %s %s %s %s", chain, "udp", dport, saddr, conn, end); #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && (v4v6_ok & IPT_V6)) fprintf(fn_ipv6, "-A %s -p %s %s %s %s %s", chain, "udp", dport, saddr, conn, end); #endif } //else if(strcmp(proto, "icmp") == 0 || strcmp(proto, "igmp") == 0 ) else if(strcmp(proto, "any") == 0) { if (v4v6_ok & IPT_V4) fprintf(fn, "-A %s %s %s %s", chain, saddr, conn, end); #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && (v4v6_ok & IPT_V6)) fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr, conn, end); #endif } else if(strcmp(proto, "tcp/udp") == 0 ){ if (v4v6_ok & IPT_V4) { fprintf(fn, "-A %s -p %s %s %s %s %s", chain, "tcp", dport, saddr, conn, end); fprintf(fn, "-A %s -p %s %s %s %s %s", chain, "udp", dport, saddr, conn, end); } #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && (v4v6_ok & IPT_V6)) { fprintf(fn_ipv6, "-A %s -p %s %s %s %s %s", chain, "tcp", dport, saddr, conn, end); fprintf(fn_ipv6, "-A %s -p %s %s %s %s %s", chain, "udp", dport, saddr, conn, end); } #endif } else fprintf(stderr, "[qos] proto doesn't exist!!\n"); //fprintf(stderr,"[qos] -A %s -p %s %s %s %s %s", chain, "tcp", port, saddr, conn, end); //tmp test } free(buf); /* lan_addr for iptables use (LAN download) */ char *a, *b, *c, *d; char lan_addr[20]; g = buf = strdup(nvram_safe_get("lan_ipaddr")); if((vstrsep(g, ".", &a, &b, &c, &d)) != 4){ fprintf(stderr,"[qos] lan_ipaddr doesn't exist!!\n"); } else{ //fprintf(stderr,"[qos] lan_ipaddr exist!!\n"); sprintf(lan_addr, "%s.%s.%s.0/24", a, b, c); fprintf(stderr,"[qos] lan_addr=%s\n", lan_addr); } free(buf); //fprintf(stderr, "[qos] down_class_num=%x\n", down_class_num); /* The default class */ i = nvram_get_int("qos_default"); if ((i < 0) || (i > 4)) i = 3; // "lowest" class_num = i + 1; #ifndef RTCONFIG_RALINK // TODO: it is only for the case, eth0 as wan, vlanx as lan fprintf(fn, "-A QOSO -d %s -j CONNMARK --set-return 0x%x/0xFF\n" // for download (LAN or wireless) "-A POSTROUTING -o br0 -j QOSO\n" // for download, interface br0 "-A QOSO -j CONNMARK --set-return 0x%x\n" "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n", lan_addr, down_class_num, class_num, pcWANIF, pcWANIF); #else fprintf(fn, "-A QOSO -j CONNMARK --set-return 0x%x\n" "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n", class_num, pcWANIF, pcWANIF); #endif #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && *wan6face) { fprintf(fn_ipv6, "-A QOSO -d %s -j CONNMARK --set-return 0x%x/0xFF\n" // for download (LAN or wireless) "-A POSTROUTING -o br0 -j QOSO\n" // for download, interface br0 "-A QOSO -j CONNMARK --set-return 0x%x\n" "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n", lan_addr, down_class_num, class_num, wan6face, wan6face); } #endif inuse |= (1 << i) | 1; // default and highest are always built sprintf(q_inuse, "%d", inuse); nvram_set("qos_inuse", q_inuse); fprintf(stderr, "[qos] qos_inuse=%d\n", inuse); /* Ingress rules */ g = buf = strdup(nvram_safe_get("qos_irates")); for (i = 0; i < 10; ++i) { if ((!g) || ((p = strsep(&g, ",")) == NULL)) continue; if ((inuse & (1 << i)) == 0) continue; if (atoi(p) > 0) { fprintf(fn, "-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0xff\n", pcWANIF); #ifdef RTCONFIG_IPV6 if (ipv6_enabled() && *wan6face) fprintf(fn_ipv6, "-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0xff\n", wan6face); #endif break; } } free(buf); fprintf(fn, "COMMIT\n"); fclose(fn); chmod(mangle_fn, 0700); eval("iptables-restore", "/tmp/mangle_rules"); #ifdef RTCONFIG_IPV6 if (ipv6_enabled()) { fprintf(fn_ipv6, "COMMIT\n"); fclose(fn_ipv6); chmod(mangle_fn_ipv6, 0700); eval("ip6tables-restore", "/tmp/mangle_rules_ipv6"); } #endif fprintf(stderr, "[qos] iptables DONE!\n"); }
// used for various testing static int rctest_main(int argc, char *argv[]) { int on; if (argc < 3) { _dprintf("test what?\n"); } else if (strcmp(argv[1], "rc_service")==0) { notify_rc(argv[2]); } else if(strcmp(argv[1], "get_phy_status")==0) { int mask; mask = atoi(argv[2]); TRACE_PT("debug for phy_status %x\n", get_phy_status(mask)); } else if(strcmp(argv[1], "get_phy_speed")==0) { int mask; mask = atoi(argv[2]); TRACE_PT("debug for phy_speed %x\n", get_phy_speed(mask)); } else if(strcmp(argv[1], "set_phy_ctrl")==0) { int mask, ctrl; mask = atoi(argv[2]); ctrl = atoi(argv[3]); TRACE_PT("debug for phy_speed %x\n", set_phy_ctrl(mask, ctrl)); } else if(strcmp(argv[1], "handle_notifications")==0) { handle_notifications(); } else if(strcmp(argv[1], "check_action")==0) { _dprintf("check: %d\n", check_action()); } else if(strcmp(argv[1], "nvramhex")==0) { int i; char *nv; nv = nvram_safe_get(argv[2]); _dprintf("nvram %s(%d): ", nv, strlen(nv)); for(i=0;i<strlen(nv);i++) { _dprintf(" %x", (unsigned char)*(nv+i)); } _dprintf("\n"); } else { on = atoi(argv[2]); _dprintf("%s %d\n", argv[1], on); if (strcmp(argv[1], "vlan") == 0) { if(on) start_vlan(); else stop_vlan(); } else if (strcmp(argv[1], "lan") == 0) { if(on) start_lan(); else stop_lan(); } else if (strcmp(argv[1], "wl") == 0) { if(on) { start_wl(); lanaccess_wl(); } } else if (strcmp(argv[1], "wan") == 0) { if(on) start_wan(); else stop_wan(); } else if (strcmp(argv[1], "firewall") == 0) { //if(on) start_firewall(); //else stop_firewall(); } else if (strcmp(argv[1], "watchdog") == 0) { if(on) start_watchdog(); else stop_watchdog(); } #ifdef RTCONFIG_FANCTRL else if (strcmp(argv[1], "phy_tempsense") == 0) { if(on) start_phy_tempsense(); else stop_phy_tempsense(); } #endif #ifdef RTCONFIG_BCMWL6 #ifdef RTCONFIG_PROXYSTA else if (strcmp(argv[1], "psta_monitor") == 0) { if(on) start_psta_monitor(); else stop_psta_monitor(); } #endif #endif else if (strcmp(argv[1], "qos") == 0) {//qos test if(on){ #ifdef RTCONFIG_RALINK if (module_loaded("hw_nat")) { modprobe_r("hw_nat"); sleep(1); #if 0 system("echo 0 > /proc/sys/net/ipv4/conf/default/force_igmp_version"); system("echo 0 > /proc/sys/net/ipv4/conf/all/force_igmp_version"); #endif } #endif add_iQosRules(get_wan_ifname(0)); start_iQos(); } else { #ifdef RTCONFIG_RALINK if (nvram_get_int("hwnat") && /* TODO: consider RTCONFIG_DUALWAN case */ // !nvram_match("wan0_proto", "l2tp") && // !nvram_match("wan0_proto", "pptp") && // !(nvram_get_int("fw_pt_l2tp") || nvram_get_int("fw_pt_ipsec") && // (nvram_match("wl0_radio", "0") || nvram_get_int("wl0_mrate_x")) && // (nvram_match("wl1_radio", "0") || nvram_get_int("wl1_mrate_x")) && !module_loaded("hw_nat")) { #if 0 system("echo 2 > /proc/sys/net/ipv4/conf/default/force_igmp_version"); system("echo 2 > /proc/sys/net/ipv4/conf/all/force_igmp_version"); #endif modprobe("hw_nat"); sleep(1); } #endif stop_iQos(); del_iQosRules(); } } #ifdef RTCONFIG_WEBDAV else if (strcmp(argv[1], "webdav") == 0) { if(on) start_webdav(); } #endif else if (strcmp(argv[1], "gpiow") == 0) { if(argc>=4) set_gpio(atoi(argv[2]), atoi(argv[3])); } else if (strcmp(argv[1], "gpior") == 0) { _dprintf("%d\n", get_gpio(atoi(argv[2]))); } else if (strcmp(argv[1], "gpiod") == 0) { if(argc>=4) gpio_dir(atoi(argv[2]), atoi(argv[3])); } else if (strcmp(argv[1], "init_switch") == 0) { init_switch(on); } else if (strcmp(argv[1], "set_action") == 0) { set_action(on); } else if (strcmp(argv[1], "pwr_usb") == 0) { set_pwr_usb(atoi(argv[2])); _dprintf("done.\n"); } else { printf("what?\n"); } } return 0; }
static int add_bandwidth_limiter_rules(char *pcWANIF) { FILE *fn = NULL; char *buf, *g, *p; char *enable, *addr, *dlc, *upc, *prio; char lan_addr[32]; char addr_new[32]; int addr_type; if ((fn = fopen(mangle_fn, "w")) == NULL) return -2; del_iQosRules(); // flush all rules in mangle table #ifdef RTCONFIG_RALINK const char *action = "CONNMARK --set-return"; #else const char *action = "MARK --set-mark"; #endif /* ASUSWRT qos_bw_rulelist : enable>addr>DL-Ceil>UL-Ceil>prio enable : enable or disable this rule addr : (source) IP or MAC or IP-range DL-Ceil : the max download bandwidth UL-Ceil : the max upload bandwidth prio : priority for client */ memset(lan_addr, 0, sizeof(lan_addr)); sprintf(lan_addr, "%s/%s", nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask")); fprintf(fn, "*mangle\n" ":PREROUTING ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ); g = buf = strdup(nvram_safe_get("qos_bw_rulelist")); while (g) { if ((p = strsep(&g, "<")) == NULL) break; if ((vstrsep(p, ">", &enable, &addr, &dlc, &upc, &prio)) != 5) continue; if (!strcmp(enable, "0")) continue; memset(addr_new, 0, sizeof(addr_new)); address_checker(&addr_type, addr, addr_new); //_dprintf("[BWLIT] %s: addr_type=%d, addr=%s, add_new=%s, lan_addr=%s\n", __FUNCTION__, addr_type, addr, addr_new, lan_addr); if (addr_type == TYPE_IP){ fprintf(fn, "-A POSTROUTING ! -s %s -d %s -j %s %d\n" "-A PREROUTING -s %s ! -d %s -j %s %d\n" , lan_addr, addr_new, action, atoi(prio)+10 , addr_new, lan_addr, action, atoi(prio)+10 ); } else if (addr_type == TYPE_MAC){ fprintf(fn, "-A PREROUTING -m mac --mac-source %s ! -d %s -j %s %d\n" , addr_new, lan_addr, action, atoi(prio)+10 ); } else if (addr_type == TYPE_IPRANGE){ fprintf(fn, "-A POSTROUTING ! -s %s -m iprange --dst-range %s -j %s %d\n" "-A PREROUTING -m iprange --src-range %s ! -d %s -j %s %d\n" , lan_addr, addr_new, action, atoi(prio)+10 , addr_new, lan_addr, action, atoi(prio)+10 ); } } free(buf); fprintf(fn, "COMMIT\n"); fclose(fn); chmod(mangle_fn, 0700); eval("iptables-restore", (char*)mangle_fn); _dprintf("[BWLIT] %s: create rules\n", __FUNCTION__); return 0; }
static int add_qos_rules(char *pcWANIF) { FILE *fn; #ifdef RTCONFIG_IPV6 FILE *fn_ipv6 = NULL; #endif char *buf; char *g; char *p; char *desc, *addr, *port, *prio, *transferred, *proto; int class_num; int down_class_num=6; // for download class_num = 0x6 / 0x106 int i, inuse; char q_inuse[32]; // for inuse char dport[192], saddr_1[192], saddr_2[192], proto_1[8], proto_2[8],conn[256], end[256], end2[256]; int method; int gum; int sticky_enable; const char *chain; int v4v6_ok; if((fn = fopen(mangle_fn, "w")) == NULL) return -2; inuse = sticky_enable = 0; if(get_model()==MODEL_RTAC56U || get_model()==MODEL_RTAC56S || get_model()==MODEL_RTAC68U || get_model()==MODEL_DSLAC68U || get_model()==MODEL_RTAC87U || get_model()==MODEL_RTAC3200 || get_model()==MODEL_RTAC88U || get_model()==MODEL_RTAC3100 || get_model()==MODEL_RTAC5300) manual_return = 1; if(nvram_match("qos_sticky", "0")) sticky_enable = 1; del_iQosRules(); // flush all rules in mangle table #ifdef CLS_ACT eval("ip", "link", "set", "imq0", "up"); #endif fprintf(stderr, "[qos] iptables START\n"); fprintf(fn, "*mangle\n" ":PREROUTING ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":QOSO - [0:0]\n" "-A QOSO -j CONNMARK --restore-mark --mask 0x7\n" "-A QOSO -m connmark ! --mark 0/0xff00 -j RETURN\n" ); #ifdef RTCONFIG_IPV6 if (fn_ipv6 && ipv6_enabled()) fprintf(fn_ipv6, "*mangle\n" ":PREROUTING ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":QOSO - [0:0]\n" "-A QOSO -j CONNMARK --restore-mark --mask 0x7\n" "-A QOSO -m connmark ! --mark 0/0xff00 -j RETURN\n" ); #endif g = buf = strdup(nvram_safe_get("qos_rulelist")); while (g) { /* ASUSWRT qos_rulelist : desc>addr>port>proto>transferred>prio addr : (source) IP or MAC or IP-range port : dest port proto : tcp, udp, tcp/udp, any , (icmp, igmp) transferred : min:max prio : 0-4, 0 is the highest */ if ((p = strsep(&g, "<")) == NULL) break; if((vstrsep(p, ">", &desc, &addr, &port, &proto, &transferred, &prio)) != 6) continue; class_num = atoi(prio); if ((class_num < 0) || (class_num > 4)) continue; i = 1 << class_num; ++class_num; //if (method == 1) class_num |= 0x200; if ((inuse & i) == 0) { inuse |= i; fprintf(stderr, "[qos] iptable creates, inuse=%d\n", inuse); } v4v6_ok = IPT_V4; #ifdef RTCONFIG_IPV6 if (fn_ipv6 && ipv6_enabled()) v4v6_ok |= IPT_V6; #endif /* Beginning of the Rule */ /* if transferred != NULL, class_num must bt 0x1~0x6, not 0x101~0x106 0x1~0x6 : keep tracing this connection. 0x101~0x106 : connection will be considered as marked connection, won't detect again. */ #if 0 if(strcmp(transferred, "") != 0 ) method = 1; else method = nvram_get_int("qos_method"); // strict rule ordering gum = (method == 0) ? 0x100 : 0; #else method = 1; gum = 0; #endif class_num |= gum; down_class_num |= gum; // for download chain = "QOSO"; // chain name sprintf(end , " -j CONNMARK --set-return 0x%x/0x7\n", class_num); // CONNMARK string sprintf(end2, " -j RETURN\n"); /*************************************************/ /* addr */ /* src mac or src ip or IP range */ /*************************************************/ char tmp[20], addr_t[40]; char *tmp_addr, *q_ip, *q_mac; memset(saddr_1, 0, sizeof(saddr_1)); memset(saddr_2, 0, sizeof(saddr_2)); memset(tmp, 0, sizeof(tmp)); sprintf(tmp, "%s", addr); tmp_addr = tmp; q_ip = strsep(&tmp_addr, ":"); q_mac = tmp_addr; memset(addr_t, 0, sizeof(addr_t)); sprintf(addr_t, "%s", addr); // step1: check contain '-' or not, if yes, IP-range, ex. 192.168.1.10-192.168.1.100 // step2: check addr is NULL // step3: check IP or MAC // step4: check IP contain '*' or not, if yes, IP-range // step5: check DUT's LAN IP shouldn't inside IP-range // step1: check contain '-' or not, if yes, IP-range if(strchr(addr_t, '-') == NULL){ // step2: check addr is NULL if(!strcmp(addr_t, "")){ sprintf(saddr_1, "%s", addr_t); // NULL } else{ // step2 // step3: check IP or MAC if (q_mac == NULL){ // step4: check IP contain '*' or not, if yes, IP-range if(strchr(q_ip, '*') != NULL){ char *rule; char Mask[40]; struct in_addr range_A, range_B, range_C; memset(Mask, 0, sizeof(Mask)); rule = strdup(addr_t); FindMask(rule, "*", "0", Mask); // find submask and replace "*" to "0" memset(addr_t, 0, sizeof(addr_t)); sprintf(addr_t, "%s", rule); // copy rule to addr_t for v4v6_ok unsigned int ip = inet_addr(rule); // covert rule's IP into binary form unsigned int nm = inet_addr(Mask); // covert submask into binary form unsigned int gw = inet_addr(nvram_safe_get("lan_ipaddr")); // covert DUT's LAN IP into binary form unsigned int gw_t = htonl(gw); range_A.s_addr = ntohl(gw_t - 1); range_B.s_addr = ntohl(gw_t + 1); range_C.s_addr = ip | ~nm; //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 // step5: check DUT's LAN IP shouldn't inside IP-range // DUT's LAN IP inside IP-range if( (ip & nm) == (gw & nm)){ //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 char range_B_addr[40]; sprintf(range_B_addr, "%s", inet_ntoa(range_B)); sprintf(saddr_1, "-m iprange --src-range %s-%s", rule, inet_ntoa(range_A)); // IP-range sprintf(saddr_2, "-m iprange --src-range %s-%s", range_B_addr, inet_ntoa(range_C)); // IP-range } else{ sprintf(saddr_1, "-m iprange --src-range %s-%s", rule, inet_ntoa(range_C)); // IP-range } free(rule); } else{ // step4 sprintf(saddr_1, "-s %s", addr_t); // IP } v4v6_ok &= ipt_addr_compact(addr_t, v4v6_ok, (v4v6_ok==IPT_V4)); if (!v4v6_ok) continue; } else{ // step3 sprintf(saddr_1, "-m mac --mac-source %s", addr_t); // MAC } } } else{ // step1 sprintf(saddr_1, "-m iprange --src-range %s", addr_t); // IP-range } //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 /*************************************************/ /* port */ /* single port or multi-ports */ /*************************************************/ char *tmp_port, *q_port, *q_leave; sprintf(tmp, "%s", port); tmp_port = tmp; q_port = strsep(&tmp_port, ","); q_leave = tmp_port; if(strcmp(port, "") == 0 ){ sprintf(dport, "%s", ""); } else{ if(q_leave != NULL) sprintf(dport, "-m multiport --dport %s", port); // multi port else sprintf(dport, "--dport %s", port); // single port } //fprintf(stderr, "[qos] tmp=%s, q_port=%s, q_leave=%s, port=%s\n", tmp, q_port, q_leave, port ); // tmp test /*************************************************/ /* transferred */ /* --connbytes min:max */ /* --connbytes-dir (original/reply/both) */ /* --connbytes-mode (packets/bytes/avgpkt) */ /*************************************************/ char *tmp_trans, *q_min, *q_max; long min, max ; sprintf(tmp, "%s", transferred); tmp_trans = tmp; q_min = strsep(&tmp_trans, "~"); q_max = tmp_trans; if (strcmp(transferred,"") == 0){ sprintf(conn, "%s", ""); } else{ sprintf(tmp, "%s", q_min); min = atol(tmp); if(strcmp(q_max,"") == 0) // q_max == NULL sprintf(conn, "-m connbytes --connbytes %ld:%s --connbytes-dir both --connbytes-mode bytes", min*1024, q_max); else{// q_max != NULL sprintf(tmp, "%s", q_max); max = atol(tmp); sprintf(conn, "-m connbytes --connbytes %ld:%ld --connbytes-dir both --connbytes-mode bytes", min*1024, max*1024-1); } } //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 /*************************************************/ /* proto */ /* tcp, udp, tcp/udp, any, (icmp, igmp) */ /*************************************************/ memset(proto_1, 0, sizeof(proto_1)); memset(proto_2, 0, sizeof(proto_2)); if(!strcmp(proto, "tcp")) { sprintf(proto_1, "-p tcp"); sprintf(proto_2, "NO"); } else if(!strcmp(proto, "udp")) { sprintf(proto_1, "-p udp"); sprintf(proto_2, "NO"); } else if(!strcmp(proto, "any")) { sprintf(proto_1, "%s", ""); sprintf(proto_2, "NO"); } else if(!strcmp(proto, "tcp/udp")) { sprintf(proto_1, "-p tcp"); sprintf(proto_2, "-p udp"); } else{ sprintf(proto_1, "NO"); sprintf(proto_2, "NO"); } //fprintf(stderr, "[qos] proto_1=%s, proto_2=%s, proto=%s\n", proto_1, proto_2, proto); // tmp test /*******************************************************************/ /* */ /* build final rule for check proto_1, proto_2, saddr_1, saddr_2 */ /* */ /*******************************************************************/ // step1. check proto != "NO" // step2. if proto = any, no proto / dport // step3. check saddr for ip-range; saddr_1 could be empty, dport only if (v4v6_ok & IPT_V4){ // step1. check proto != "NO" if(strcmp(proto_1, "NO")){ // step2. if proto = any, no proto / dport if(strcmp(proto_1, "")){ // step3. check saddr for ip-range;saddr_1 could be empty, dport only fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end2); } } else{ fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end2); } } } // step1. check proto != "NO" if(strcmp(proto_2, "NO")){ // step2. if proto = any, no proto / dport if(strcmp(proto_2, "")){ // step3. check saddr for ip-range;saddr_1 could be empty, dport only fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end2); } } else{ fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s", chain, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end); if(manual_return) fprintf(fn, "-A %s %s %s %s", chain, saddr_2, conn, end2); } } } } #ifdef RTCONFIG_IPV6 if (fn_ipv6 && ipv6_enabled() && (v4v6_ok & IPT_V6)){ // step1. check proto != "NO" if(strcmp(proto_1, "NO")){ // step2. if proto = any, no proto / dport if(strcmp(proto_1, "")){ // step3. check saddr for ip-range;saddr_1 could be empty, dport only fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_1, dport, saddr_2, conn, end2); } } else{ fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end2); } } } // step1. check proto != "NO" if(strcmp(proto_2, "NO")){ // step2. if proto = any, no proto / dport if(strcmp(proto_2, "")){ // step3. check saddr for ip-range;saddr_1 could be empty, dport only fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s %s %s", chain, proto_2, dport, saddr_2, conn, end2); } } else{ fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_1, conn, end2); if(strcmp(saddr_2, "")){ fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end); if(manual_return) fprintf(fn_ipv6, "-A %s %s %s %s", chain, saddr_2, conn, end2); } } } } #endif } free(buf); /* lan_addr for iptables use (LAN download) */ char *a, *b, *c, *d; char lan_addr[20]; g = buf = strdup(nvram_safe_get("lan_ipaddr")); if((vstrsep(g, ".", &a, &b, &c, &d)) != 4){ fprintf(stderr,"[qos] lan_ipaddr doesn't exist!!\n"); } else{ sprintf(lan_addr, "%s.%s.%s.0/24", a, b, c); fprintf(stderr,"[qos] lan_addr=%s\n", lan_addr); } free(buf); //fprintf(stderr, "[qos] down_class_num=%x\n", down_class_num); /* The default class */ i = nvram_get_int("qos_default"); if ((i < 0) || (i > 4)) i = 3; // "lowest" class_num = i + 1; #ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan if(strncmp(pcWANIF, "ppp", 3)==0){ // ppp related interface doesn't need physdev // do nothing } else{ /* for WLAN to LAN bridge packet */ // ebtables : identify bridge packet add_EbtablesRules(); // for multicast fprintf(fn, "-A QOSO -d 224.0.0.0/4 -j CONNMARK --set-return 0x%x/0x7\n", down_class_num); if(manual_return) fprintf(fn , "-A QOSO -d 224.0.0.0/4 -j RETURN\n"); // for download (LAN or wireless) fprintf(fn, "-A QOSO -d %s -j CONNMARK --set-return 0x%x/0x7\n", lan_addr, down_class_num); if(manual_return) fprintf(fn , "-A QOSO -d %s -j RETURN\n", lan_addr); /* Requires bridge netfilter, but slows down and breaks EMF/IGS IGMP IPTV Snooping // for WLAN to LAN bridge issue fprintf(fn, "-A POSTROUTING -d %s -m physdev --physdev-is-in -j CONNMARK --set-return 0x6/0x7\n", lan_addr); */ // for download, interface br0 fprintf(fn, "-A POSTROUTING -o br0 -j QOSO\n"); } #endif fprintf(fn, "-A QOSO -j CONNMARK --set-return 0x%x/0x7\n" "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n", class_num, pcWANIF, pcWANIF); if(manual_return) fprintf(fn , "-A QOSO -j RETURN\n"); #ifdef RTCONFIG_IPV6 if (fn_ipv6 && ipv6_enabled() && *wan6face) { #ifdef CONFIG_BCMWL5 // TODO: it is only for the case, eth0 as wan, vlanx as lan if(strncmp(wan6face, "ppp", 3)==0){ // ppp related interface doesn't need physdev // do nothing } else{ /* for WLAN to LAN bridge packet */ // ebtables : identify bridge packet add_EbtablesRules(); // for multicast fprintf(fn_ipv6, "-A QOSO -d 224.0.0.0/4 -j CONNMARK --set-return 0x%x/0x7\n", down_class_num); if(manual_return) fprintf(fn_ipv6, "-A QOSO -d 224.0.0.0/4 -j RETURN\n"); // for download (LAN or wireless) fprintf(fn_ipv6, "-A QOSO -d %s -j CONNMARK --set-return 0x%x/0x7\n", lan_addr, down_class_num); if(manual_return) fprintf(fn_ipv6, "-A QOSO -d %s -j RETURN\n", lan_addr); /* Requires bridge netfilter, but slows down and breaks EMF/IGS IGMP IPTV Snooping // for WLAN to LAN bridge issue fprintf(fn_ipv6, "-A POSTROUTING -d %s -m physdev --physdev-is-in -j CONNMARK --set-return 0x6/0x7\n", lan_addr); */ // for download, interface br0 fprintf(fn_ipv6, "-A POSTROUTING -o br0 -j QOSO\n"); } #endif fprintf(fn_ipv6, "-A QOSO -j CONNMARK --set-return 0x%x/0x7\n" "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n", class_num, wan6face, wan6face); if(manual_return) fprintf(fn_ipv6, "-A QOSO -j RETURN\n"); } #endif inuse |= (1 << i) | 1; // default and highest are always built sprintf(q_inuse, "%d", inuse); nvram_set("qos_inuse", q_inuse); fprintf(stderr, "[qos] qos_inuse=%d\n", inuse); /* Ingress rules */ g = buf = strdup(nvram_safe_get("qos_irates")); for (i = 0; i < 10; ++i) { if ((!g) || ((p = strsep(&g, ",")) == NULL)) continue; if ((inuse & (1 << i)) == 0) continue; if (atoi(p) > 0) { fprintf(fn, "-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0x7\n", pcWANIF); #ifdef CLS_ACT fprintf(fn, "-A PREROUTING -i %s -j IMQ --todev 0\n", pcWANIF); #endif #ifdef RTCONFIG_IPV6 if (fn_ipv6 && ipv6_enabled() && *wan6face) { fprintf(fn_ipv6, "-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0x7\n", wan6face); #ifdef CLS_ACT fprintf(fn_ipv6, "-A PREROUTING -i %s -j IMQ --todev 0\n", wan6face); #endif } #endif break; } } free(buf); fprintf(fn, "COMMIT\n"); fclose(fn); chmod(mangle_fn, 0700); eval("iptables-restore", (char*)mangle_fn); #ifdef RTCONFIG_IPV6 if (fn_ipv6 && ipv6_enabled()) { fprintf(fn_ipv6, "COMMIT\n"); fclose(fn_ipv6); chmod(mangle_fn_ipv6, 0700); // eval("ip6tables-restore", (char*)mangle_fn_ipv6); } #endif fprintf(stderr, "[qos] iptables DONE!\n"); return 0; }
// used for various testing static int rctest_main(int argc, char *argv[]) { int on; if (argc < 2) { _dprintf("test what?\n"); } else if (strcmp(argv[1], "rc_service")==0) { notify_rc(argv[2]); } else if(strcmp(argv[1], "get_phy_status")==0) { int mask; mask = atoi(argv[2]); TRACE_PT("debug for phy_status %x\n", get_phy_status(mask)); } else if(strcmp(argv[1], "get_phy_speed")==0) { int mask; mask = atoi(argv[2]); TRACE_PT("debug for phy_speed %x\n", get_phy_speed(mask)); } else if(strcmp(argv[1], "set_phy_ctrl")==0) { int mask, ctrl; mask = atoi(argv[2]); ctrl = atoi(argv[3]); TRACE_PT("debug for phy_speed %x\n", set_phy_ctrl(mask, ctrl)); } else if(strcmp(argv[1], "handle_notifications")==0) { handle_notifications(); } else if(strcmp(argv[1], "check_action")==0) { _dprintf("check: %d\n", check_action()); } else if(strcmp(argv[1], "nvramhex")==0) { int i; char *nv; nv = nvram_safe_get(argv[2]); _dprintf("nvram %s(%d): ", nv, strlen(nv)); for(i=0;i<strlen(nv);i++) { _dprintf(" %x", (unsigned char)*(nv+i)); } _dprintf("\n"); } else { on = atoi(argv[2]); _dprintf("%s %d\n", argv[1], on); if (strcmp(argv[1], "vlan") == 0) { if(on) start_vlan(); else stop_vlan(); } else if (strcmp(argv[1], "lan") == 0) { if(on) start_lan(); else stop_lan(); } else if (strcmp(argv[1], "wl") == 0) { if(on) { start_wl(); lanaccess_wl(); } } else if (strcmp(argv[1], "wan") == 0) { if(on) start_wan(); else stop_wan(); } else if (strcmp(argv[1], "wan_port") == 0) { if(on) start_wan_port(); else stop_wan_port(); } else if (strcmp(argv[1], "firewall") == 0) { //if(on) start_firewall(); //else stop_firewall(); } else if (strcmp(argv[1], "watchdog") == 0) { if(on) start_watchdog(); else stop_watchdog(); } #if ! (defined(RTCONFIG_QCA) || defined(RTCONFIG_RALINK)) else if (strcmp(argv[1], "watchdog02") == 0) { if(on) start_watchdog02(); else stop_watchdog02(); } #endif /* ! (RTCONFIG_QCA || RTCONFIG_RALINK) */ else if (strcmp(argv[1], "sw_devled") == 0) { if(on) start_sw_devled(); else stop_sw_devled(); } #ifdef RTCONFIG_FANCTRL else if (strcmp(argv[1], "phy_tempsense") == 0) { if(on) start_phy_tempsense(); else stop_phy_tempsense(); } #endif #ifdef RTCONFIG_BCMWL6 #ifdef RTCONFIG_PROXYSTA else if (strcmp(argv[1], "psta_monitor") == 0) { if(on) start_psta_monitor(); else stop_psta_monitor(); } #endif #endif #ifdef RTCONFIG_IPERF else if (strcmp(argv[1], "monitor") == 0) { if(on) start_monitor(); else stop_monitor(); } #endif else if (strcmp(argv[1], "qos") == 0) {//qos test if(on){ #ifdef RTCONFIG_RALINK if (module_loaded("hw_nat")) { modprobe_r("hw_nat"); sleep(1); #if 0 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "0", 0, 0); f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "0", 0, 0); #endif } #endif add_iQosRules(get_wan_ifname(wan_primary_ifunit())); #ifdef RTCONFIG_BWDPI if(nvram_get_int("qos_type") == 1) { start_dpi_engine_service(); // force to rebuild firewall to avoid some loopback issue if (nvram_match("fw_nat_loopback", "2")) start_firewall(wan_primary_ifunit(), 0); } else #endif start_iQos(); } else { #ifdef RTCONFIG_RALINK if (nvram_get_int("hwnat") && /* TODO: consider RTCONFIG_DUALWAN case */ // !nvram_match("wan0_proto", "l2tp") && // !nvram_match("wan0_proto", "pptp") && // !(nvram_get_int("fw_pt_l2tp") || nvram_get_int("fw_pt_ipsec") && // (nvram_match("wl0_radio", "0") || nvram_get_int("wl0_mrate_x")) && // (nvram_match("wl1_radio", "0") || nvram_get_int("wl1_mrate_x")) && !module_loaded("hw_nat")) { #if 0 f_write_string("/proc/sys/net/ipv4/conf/default/force_igmp_version", "2", 0, 0); f_write_string("/proc/sys/net/ipv4/conf/all/force_igmp_version", "2", 0, 0); #endif #if defined(RTN14U) || defined(RTAC52U) || defined(RTAC51U) || defined(RTN11P) || defined(RTN300) || defined(RTN54U) || defined(RTAC1200HP) || defined(RTN56UB1) || defined(RTAC54U) || defined(RTN56UB2) if (!(!nvram_match("switch_wantag", "none")&&!nvram_match("switch_wantag", ""))) #endif { modprobe("hw_nat"); sleep(1); } } #endif #ifdef RTCONFIG_BWDPI if(nvram_get_int("qos_type") == 1){ stop_dpi_engine_service(1); } else #endif stop_iQos(); del_iQosRules(); } } #ifdef RTCONFIG_WEBDAV else if (strcmp(argv[1], "webdav") == 0) { if(on) start_webdav(); } #endif #ifdef RTCONFIG_TUNNEL else if (strcmp(argv[1], "mastiff") == 0) { if(on) start_mastiff(); } #endif else if (strcmp(argv[1], "gpiow") == 0) { if(argc>=4) set_gpio(atoi(argv[2]), atoi(argv[3])); } else if (strcmp(argv[1], "gpior") == 0) { printf("%d\n", get_gpio(atoi(argv[2]))); } else if (strcmp(argv[1], "gpiod") == 0) { if(argc>=4) gpio_dir(atoi(argv[2]), atoi(argv[3])); } else if (strcmp(argv[1], "init_switch") == 0) { init_switch(); } else if (strcmp(argv[1], "set_action") == 0) { set_action(on); } else if (strcmp(argv[1], "pwr_usb") == 0) { set_pwr_usb(atoi(argv[2])); _dprintf("done.\n"); } else if (strcmp(argv[1], "enc_chk") == 0) { unsigned char enc_buf[ENC_WORDS_LEN]; unsigned char dec_buf[DATA_WORDS_LEN + 1]; _dprintf("get enc str:[%s]\n", enc_str(argv[2], (char *) enc_buf)); _dprintf("get dec str:[%s]\n", dec_str((char *) enc_buf, (char *) dec_buf)); _dprintf("done(%d)\n", strcmp(argv[2], (const char *) dec_buf)); } #ifdef RTCONFIG_BCMFA else if (strcmp(argv[1], "fa_rev") == 0) { _dprintf("(%d) done.\n", get_fa_rev()); } else if (strcmp(argv[1], "fa_dump") == 0) { _dprintf("(%d) done.\n", get_fa_dump()); } #endif else { printf("what?\n"); } } return 0; }