void start_arpbind(void) { char *nvp, *nv, *b; const char *ipaddr, *macaddr; const char *name, *bind; nvp = nv = strdup(nvram_safe_get("dhcpd_static")); if (!nv) return; // clear arp table first stop_arpbind(); while ((b = strsep(&nvp, ">")) != NULL) { /* macaddr<ip.ad.dr.ess<hostname<arpbind>anotherhwaddr<other.ip.addr.ess<othername<arpbind */ if ((vstrsep(b, "<", &macaddr, &ipaddr, &name, &bind)) != 4) continue; if (strchr(macaddr,',') != NULL) continue; if (strcmp(bind,"1") == 0) eval ("arp", "-s", (char *)ipaddr, (char *)macaddr); } free(nv); }
void write_chap_secret(char *file) { FILE *fp; char nv[MAXLEN_TCAPI_MSG], *nvp, *b; char *username, *passwd; char namebuf[256], passwdbuf[256]; int index = 1; char listname[32] = {0}; fp=fopen(file, "w"); if (fp==NULL) return; if( tcapi_get(VPN_DATA, "pptpd_clientlist", nv) == TCAPI_PROCESS_OK) { nvp = nv; while ((b = strsep(&nvp, "<")) != NULL) { if((vstrsep(b, ">", &username, &passwd)!=2)) continue; if(strlen(username)==0||strlen(passwd)==0) continue; fprintf(fp, "%s * %s *\n", pptp_encode(username, namebuf), pptp_encode(passwd, passwdbuf)); } } for(index = 1; index < 16; index++) { memset(nv, 0, sizeof(nv)); sprintf(listname, "pptpd_clientlist%d", index); if( tcapi_get(VPN_DATA, listname, nv) == TCAPI_PROCESS_OK) { nvp = nv; while ((b = strsep(&nvp, "<")) != NULL) { if((vstrsep(b, ">", &username, &passwd)!=2)) continue; if(strlen(username)==0||strlen(passwd)==0) continue; fprintf(fp, "%s * %s *\n", pptp_encode(username, namebuf), pptp_encode(passwd, passwdbuf)); } } } fclose(fp); }
void ipt_triggered(ipt_table_t table) { char *nv, *nvp, *b; const char *proto, *mports, *fports; const char *c; char *p; int i; int first; char s[256]; nvp = nv = strdup(nvram_safe_get("trigforward")); if (!nv) return; first = 1; while ((b = strsep(&nvp, ">")) != NULL) { if ((vstrsep(b, "<", &c, &proto, &mports, &fports) != 4) || (*c != '1')) continue; for (i = 0; i < 2; ++i) { if ((1 << i) & (*proto - '0')) { if (first) { // should only be created if there is at least one enabled if (table == IPT_TABLE_NAT) { ipt_write("-A %s -j TRIGGER --trigger-type dnat\n", chain_wan_prerouting); goto QUIT; } ipt_write(":triggers - [0:0]\n" "-A wanout -j triggers\n" "-A wanin -j TRIGGER --trigger-type in\n"); first = 0; } strlcpy(s, mports, sizeof(s)); if ((p = strchr(s, ':')) != NULL) *p = '-'; if ((p = strchr(fports, ':')) != NULL) *p = '-'; c = tcpudp[i]; ipt_write("-A triggers -p %s -m %s --dport %s " "-j TRIGGER --trigger-type out --trigger-proto %s --trigger-match %s --trigger-relate %s\n", c, c, mports, c, s, fports); // can't use multiport... trigger-match must be set to the same // ports as dport since it's used to refresh timer during inbound -- zzz } } } QUIT: free(nv); }
void ip6t_forward(void) { char *nv, *nvp, *b; const char *proto, *saddr, *daddr, *dports, *desc; const char *c; const char *mdport; int i; char src[128]; char dst[128]; nvp = nv = strdup(nvram_safe_get("ipv6_portforward")); if (!nv) return; while ((b = strsep(&nvp, ">")) != NULL) { /* 1<3<2001:23:45:67::/64<2600:abc:def:123::1<30,40-45<desc 1 = enabled 3 = tcp & udp 2001:23:45:67::/64 = src addr 2600:abc:def:123::1 or 2001:10:11:12::/112 = dst addr (optional) 30,40-45 = dst port desc = desc */ if ((vstrsep(b, "<", &c, &proto, &saddr, &daddr, &dports, &desc) != 6) || (*c != '1')) continue; if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V6, 1, "IPv6 port forwarding", desc)) continue; if (!ipt_addr(dst, sizeof(dst), daddr, "dst", IPT_V6, 1, "IPv6 port forwarding", desc)) continue; mdport = (strchr(dports, ',') != NULL) ? "-m multiport --dports" : "--dport"; for (i = 0; i < 2; ++i) { if ((1 << i) & (*proto - '0')) { c = tcpudp[i]; ip6t_write("-A wanin %s -p %s -m %s %s%s %s %s -j %s\n", src, c, c, (*daddr) ? "-d " : "", daddr, mdport, dports, chain_in_accept); } } } free(nv); }
void start_nfs(void) { FILE *fp; char *buf; char *g; char *p; int i; char *dir,*address,*access,*sync,*subtree,*other; // only if enable... if( nvram_match( "nfs_enable", "1" ) ) { // read exports from nvram if ((buf = strdup(nvram_safe_get("nfs_exports"))) != NULL) { // writing data to file if( !( fp = fopen( "/etc/exports", "w" ) ) ) { perror( "/etc/exports" ); return; } g = buf; // dir < address < access < sync < subtree < other while ((p = strsep(&g, ">")) != NULL) { i = vstrsep(p, "<", &dir, &address, &access, &sync, &subtree, &other); if (i!=6) continue; fprintf(fp, "%s %s(%s,%s,%s,%s)\n", dir,address,access,sync,subtree,other); } free(buf); } fclose( fp ); chmod( "/etc/exports", 0644 ); } xstart( "/usr/sbin/nfs.rc" ); return; }
void check_nmp_db(CLIENT_DETAIL_INFO_TABLE *p_client_tab, int client_no) { char new_mac[13]; char *search_list, *nv, *nvp, *b; char *db_mac, *db_user_def, *db_device_name, *db_type, *db_http, *db_printer, *db_itune; if(!nmp_client_list) return; NMP_DEBUG("check_nmp_db:\n"); search_list = strdup(nmp_client_list); convert_mac_to_string(p_client_tab->mac_addr[client_no], new_mac); NMP_DEBUG("search_list= %s\n", search_list); if(strstr(search_list, new_mac)==NULL) return; nvp = nv = search_list; while (nv && (b = strsep(&nvp, "<")) != NULL) { if (vstrsep(b, ">", &db_mac, &db_user_def, &db_device_name, &db_type, &db_http, &db_printer, &db_itune) != 7) continue; NMP_DEBUG_M("DB: %s,%s,%s,%s,%s,%s,%s\n", db_mac, db_user_def, db_device_name, db_type, db_http, db_printer, db_itune); if (!strcmp(db_mac, new_mac)) { NMP_DEBUG("*** %s at DB!!! Update to memory\n",new_mac); strcpy(p_client_tab->user_define[client_no], db_user_def); strcpy(p_client_tab->device_name[client_no], db_device_name); p_client_tab->type[client_no] = atoi(db_type); p_client_tab->http[client_no] = atoi(db_http); p_client_tab->printer[client_no] = atoi(db_printer); p_client_tab->itune[client_no] = atoi(db_itune); break; } } SAFE_FREE(search_list); }
void write_chap_secret(char *file) { FILE *fp; char *nv, *nvp, *b; char *username, *passwd; char namebuf[256], passwdbuf[256]; fp=fopen(file, "w"); if (fp==NULL) return; nv = nvp = strdup(nvram_safe_get("pptpd_clientlist")); if(nv) { while ((b = strsep(&nvp, "<")) != NULL) { if((vstrsep(b, ">", &username, &passwd)!=2)) continue; if(strlen(username)==0||strlen(passwd)==0) continue; fprintf(fp, "%s * %s *\n", pptp_encode(username, namebuf), pptp_encode(passwd, passwdbuf)); } free(nv); } fclose(fp); }
// read nvram into files void new_arpbind_start(void) { FILE *f; char *buf; char *g; char *p; char *ipaddr;//ip address char *macaddr;//mac address char *s = "/tmp/new_arpbind_start.sh"; char *argv[3]; int pid; int i; char lan[24]; const char *router_ip; int host[256]; //arpbind is enable if (!nvram_get_int("new_arpbind_enable")) return; //read arpbind_list from nvram g = buf = strdup(nvram_safe_get("new_arpbind_list")); //read arpbind_list into file if ((f = fopen(s, "w")) == NULL) return; fprintf(f, "#!/bin/sh\n" "for HOST in `awk '{if($1!=\"IP\")print $1}' /proc/net/arp`; do arp -d $HOST; done\n" ); memset(host, 0, sizeof(host)); //get network ip prefix router_ip = nvram_safe_get("lan_ipaddr"); strlcpy(lan, router_ip, sizeof(lan)); if ((p = strrchr(lan, '.')) != NULL) { host[atoi(p+1)] = 1; *p = '\0'; } while (g) { /* macaddr<ipaddr */ if ((p = strsep(&g, ">")) == NULL) break; i = vstrsep(p, "<", &macaddr, &ipaddr); fprintf(f, "arp -s %s %s\n", ipaddr, macaddr); if ((p = strrchr(ipaddr, '.')) != NULL) { *p = '\0'; if (!strcmp(ipaddr, lan)) host[atoi(p+1)] = 1; } } if (nvram_get_int("new_arpbind_only")) { for (i = 1; i < 255; i++) { if (!host[i]) { fprintf(f, "arp -s %s.%d 00:00:00:00:00:00\n", lan, i); } } } free(buf); fclose(f); chmod(s, 0700); chdir("/tmp"); argv[0] = s; argv[1] = NULL; argv[2] = NULL; if (_eval(argv, NULL, 0, &pid) != 0) { pid = -1; } else { kill(pid, 0); } chdir("/"); }
int update_dsl_iptv_variables() { char *nv, *nvp, *b; char *vpi, *vci, *proto, *encap, *vid; int unit = 0; char prefix[] = "dslxxx_xxxxxxxx"; char tmp[64]; _dprintf("dsltmp_cfg_iptv_pvclist=%s\n", nvram_safe_get("dsltmp_cfg_iptv_pvclist")); nvp = nv = strdup(nvram_safe_get("dsltmp_cfg_iptv_pvclist")); while(nv && (b = strsep(&nvp, "<")) != NULL){ if((vstrsep(b, ">", &vpi, &vci, &proto, &encap, &vid) != 5)) continue; unit++; _dprintf("vpi=[%s], vci=[%s], proto=[%s], encap=[%s], vid=[%s]\n", vpi, vci, proto, encap, vid); if(nvram_match("dsltmp_transmode", "atm")) { snprintf(prefix, sizeof(prefix), "dsl%d_", unit); nvram_set(strcat_r(prefix, "vpi", tmp), vpi); nvram_set(strcat_r(prefix, "vci", tmp), vci); nvram_set(strcat_r(prefix, "encap", tmp), encap); } else { //ptm snprintf(prefix, sizeof(prefix), "dsl8.%d_", unit); } nvram_set(strcat_r(prefix, "enable", tmp), "1"); if(!strcmp(proto, "0")) { nvram_set(strcat_r(prefix, "proto", tmp), "pppoe"); } else if(!strcmp(proto, "1")) { nvram_set(strcat_r(prefix, "proto", tmp), "pppoa"); } else if(!strcmp(proto, "2")) { nvram_set(strcat_r(prefix, "proto", tmp), "dhcp"); } else if(!strcmp(proto, "3")) { nvram_set(strcat_r(prefix, "proto", tmp), "bridge"); } else if(!strcmp(proto, "4")) { nvram_set(strcat_r(prefix, "proto", tmp), "ipoa"); } else { nvram_set(strcat_r(prefix, "proto", tmp), "bridge"); } if(strlen(vid)) { nvram_set(strcat_r(prefix, "dot1q", tmp), "1"); nvram_set(strcat_r(prefix, "vid", tmp), vid); } } free(nv); if(unit) { if(nvram_match("switch_stb_x", "1") && (nvram_get_int("dslx_config_num") > 1) ) { nvram_set("dsltmp_qis_reboot", "0"); } else { nvram_set("switch_stb_x", "1"); nvram_set("wans_lanport", "4"); nvram_set("dsltmp_qis_reboot", "1"); } } else { if(nvram_match("switch_stb_x", "0")) { nvram_set("dsltmp_qis_reboot", "0"); } else { nvram_set("switch_stb_x", "0"); nvram_set("dsl1_enable", "0"); nvram_set("dsl2_enable", "0"); nvram_set("dsl3_enable", "0"); nvram_set("dsl4_enable", "0"); nvram_set("dsl5_enable", "0"); nvram_set("dsl6_enable", "0"); nvram_set("dsl7_enable", "0"); #ifdef RTCONFIG_VDSL nvram_set("dsl8.1_enable", "0"); nvram_set("dsl8.2_enable", "0"); nvram_set("dsl8.3_enable", "0"); nvram_set("dsl8.4_enable", "0"); nvram_set("dsl8.5_enable", "0"); nvram_set("dsl8.6_enable", "0"); nvram_set("dsl8.7_enable", "0"); #endif nvram_set("dsltmp_qis_reboot", "1"); } } return 0; }
void write_to_nvram(CLIENT_DETAIL_INFO_TABLE *p_client_tab) { char new_mac[13], *dst_list; char *nv, *nvp, *b, *search_list; char *db_mac, *db_user_def, *db_device_name, *db_type, *db_http, *db_printer, *db_itune; convert_mac_to_string(p_client_tab->mac_addr[p_client_tab->detail_info_num], new_mac); NMP_DEBUG("*** write_to_nvram: %s ***\n",new_mac); search_list = strdup(nmp_client_list); b = strstr(search_list, new_mac); if(b!=NULL) { //find the client in the DB dst_list = malloc(sizeof(char)*10000); NMP_DEBUG_M("client data in DB: %s\n", new_mac); nvp = nv = b; *(b-1) = '\0'; strcpy(dst_list, search_list); NMP_DEBUG_M("dst_list= %s\n", dst_list); //b++; while (nv && (b = strsep(&nvp, "<")) != NULL) { if (b == NULL) continue; if (vstrsep(b, ">", &db_mac, &db_user_def, &db_device_name, &db_type, &db_http, &db_printer, &db_itune) != 7) continue; NMP_DEBUG_M("%s,%s,%d,%d,%d,%d\n", db_mac, db_user_def, db_device_name, atoi(db_type), atoi(db_http), atoi(db_printer), atoi(db_itune)); if (!strcmp(p_client_tab->device_name[p_client_tab->detail_info_num], db_device_name) && p_client_tab->type[p_client_tab->detail_info_num] == atoi(db_type) && p_client_tab->http[p_client_tab->detail_info_num] == atoi(db_http) && p_client_tab->printer[p_client_tab->detail_info_num] == atoi(db_printer) && p_client_tab->itune[p_client_tab->detail_info_num] == atoi(db_itune) ) { NMP_DEBUG("DATA the same!\n"); return; } sprintf(dst_list, "%s<%s<%s", dst_list, db_mac, db_user_def); if (strcmp(p_client_tab->device_name[p_client_tab->detail_info_num], "")) { NMP_DEBUG("Update device name: %s.\n", p_client_tab->device_name[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%s", dst_list, p_client_tab->device_name[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_device_name); if (p_client_tab->type[p_client_tab->detail_info_num] != 6) { client_updated = 1; NMP_DEBUG("Update type: %d\n", p_client_tab->type[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->type[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_type); if (!strcmp(db_http, "0") ) { client_updated = 1; NMP_DEBUG("Update http: %d\n", p_client_tab->http[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->http[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_http); if (!strcmp(db_printer, "0") ) { client_updated = 1; NMP_DEBUG("Update type: %d\n", p_client_tab->printer[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->printer[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_printer); if (!strcmp(db_itune, "0")) { client_updated = 1; NMP_DEBUG("Update type: %d\n", p_client_tab->itune[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->itune[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_itune); if(nvp != NULL) { strcat(dst_list, "<"); strcat(dst_list, nvp); } nmp_client_list = strdup(dst_list); free(dst_list); NMP_DEBUG_M("*** Update nmp_client_list:\n%s\n", nmp_client_list); nvram_set("nmp_client_list", nmp_client_list); break; } } else { //new client NMP_DEBUG_M("new client: %d-%s,%s,%d\n",p_client_tab->detail_info_num, new_mac, p_client_tab->device_name[p_client_tab->detail_info_num], p_client_tab->type[p_client_tab->detail_info_num]); sprintf(nmp_client_list,"%s<%s>>%s>%d>%d>%d>%d", nmp_client_list, new_mac, p_client_tab->device_name[p_client_tab->detail_info_num], p_client_tab->type[p_client_tab->detail_info_num], p_client_tab->http[p_client_tab->detail_info_num], p_client_tab->printer[p_client_tab->detail_info_num], p_client_tab->itune[p_client_tab->detail_info_num] ); nvram_set("nmp_client_list", nmp_client_list); } }
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"); }
void ipt_qoslimit(int chain) { char *buf; char *g; char *p; char *ibw,*obw;//bandwidth char seq[4];//mark number int iSeq = 10; char *ipaddr_old; char ipaddr[30];//ip address char *dlrate,*dlceil;//guaranteed rate & maximum rate for download char *ulrate,*ulceil;//guaranteed rate & maximum rate for upload char *priority;//priority char *lanipaddr; //lan ip address char *lanmask; //lan netmask char *tcplimit,*udplimit;//tcp connection limit & udp packets per second int priority_num; char *qosl_tcp,*qosl_udp; int i, address_type; //qos1 is enable if (!nvram_get_int("new_qoslimit_enable")) return; //read qos1rules from nvram g = buf = strdup(nvram_safe_get("new_qoslimit_rules")); ibw = nvram_safe_get("qos_ibw"); // Read from QOS setting - KRP obw = nvram_safe_get("qos_obw"); // Read from QOS setting - KRP lanipaddr = nvram_safe_get("lan_ipaddr"); lanmask = nvram_safe_get("lan_netmask"); qosl_tcp = nvram_safe_get("qosl_tcp"); qosl_udp = nvram_safe_get("qosl_udp"); //MANGLE if (chain == 1) { if (nvram_get_int("qosl_enable") == 1) { ipt_write( "-A POSTROUTING ! -s %s/%s -d %s/%s -j MARK --set-mark 100\n" "-A PREROUTING -s %s/%s ! -d %s/%s -j MARK --set-mark 100\n" ,lanipaddr,lanmask,lanipaddr,lanmask ,lanipaddr,lanmask,lanipaddr,lanmask); } //shibby br1 if (nvram_get_int("limit_br1_enable") == 1) { char *lan1_ipaddr; //lan1 ip address char *lan1_mask; //lan1 netmask lan1_ipaddr = nvram_safe_get("lan1_ipaddr"); lan1_mask = nvram_safe_get("lan1_netmask"); ipt_write( "-A POSTROUTING -d %s/%s -j MARK --set-mark 401\n" "-A PREROUTING -s %s/%s -j MARK --set-mark 501\n" ,lan1_ipaddr,lan1_mask ,lan1_ipaddr,lan1_mask); } //shibby br2 if (nvram_get_int("limit_br2_enable") == 1) { char *lan2_ipaddr; //lan2 ip address char *lan2_mask; //lan2 netmask lan2_ipaddr = nvram_safe_get("lan2_ipaddr"); lan2_mask = nvram_safe_get("lan2_netmask"); ipt_write( "-A POSTROUTING -d %s/%s -j MARK --set-mark 601\n" "-A PREROUTING -s %s/%s -j MARK --set-mark 701\n" ,lan2_ipaddr,lan2_mask ,lan2_ipaddr,lan2_mask); } //shibby br3 if (nvram_get_int("limit_br3_enable") == 1) { char *lan3_ipaddr; //lan3 ip address char *lan3_mask; //lan3 netmask lan3_ipaddr = nvram_safe_get("lan3_ipaddr"); lan3_mask = nvram_safe_get("lan3_netmask"); ipt_write( "-A POSTROUTING -d %s/%s -j MARK --set-mark 801\n" "-A PREROUTING -s %s/%s -j MARK --set-mark 901\n" ,lan3_ipaddr,lan3_mask ,lan3_ipaddr,lan3_mask); } } //NAT if (chain == 2) { if (nvram_get_int("qosl_enable") == 1) { if (nvram_get_int("qosl_tcp") > 0) { ipt_write( "-A PREROUTING -s %s/%s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n" ,lanipaddr,lanmask,qosl_tcp); } if (nvram_get_int("qosl_udp") > 0) { ipt_write( "-A PREROUTING -s %s/%s -p udp -m limit --limit %s/sec -j ACCEPT\n" ,lanipaddr,lanmask,qosl_udp); } } } while (g) { /* ipaddr_old<dlrate<dlceil<ulrate<ulceil<priority<tcplimit<udplimit */ if ((p = strsep(&g, ">")) == NULL) break; i = vstrsep(p, "<", &ipaddr_old, &dlrate, &dlceil, &ulrate, &ulceil, &priority, &tcplimit, &udplimit); if (i!=8) continue; priority_num = atoi(priority); if ((priority_num < 0) || (priority_num > 5)) continue; if (!strcmp(ipaddr_old,"")) continue; address_checker (&address_type, ipaddr_old, ipaddr); sprintf(seq,"%d",iSeq); iSeq++; if (!strcmp(dlceil,"")) strcpy(dlceil, dlrate); if (strcmp(dlrate,"") && strcmp(dlceil, "")) { if(chain == 1) { switch (address_type) { case IP_ADDRESS: ipt_write( "-A POSTROUTING ! -s %s/%s -d %s -j MARK --set-mark %s\n" ,lanipaddr,lanmask,ipaddr,seq); break; case MAC_ADDRESS: break; case IP_RANGE: ipt_write( "-A POSTROUTING ! -s %s/%s -m iprange --dst-range %s -j MARK --set-mark %s\n" ,lanipaddr,lanmask,ipaddr,seq); break; } } } if (!strcmp(ulceil,"")) strcpy(ulceil, ulrate); if (strcmp(ulrate,"") && strcmp(ulceil, "")) { if (chain == 1) { switch (address_type) { case IP_ADDRESS: ipt_write( "-A PREROUTING -s %s ! -d %s/%s -j MARK --set-mark %s\n" ,ipaddr,lanipaddr,lanmask,seq); break; case MAC_ADDRESS: ipt_write( "-A PREROUTING -m mac --mac-source %s ! -d %s/%s -j MARK --set-mark %s\n" ,ipaddr,lanipaddr,lanmask,seq); break; case IP_RANGE: ipt_write( "-A PREROUTING -m iprange --src-range %s ! -d %s/%s -j MARK --set-mark %s\n" ,ipaddr,lanipaddr,lanmask,seq); break; } } } if(atoi(tcplimit) > 0){ if (chain == 2) { switch (address_type) { case IP_ADDRESS: ipt_write( "-A PREROUTING -s %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n" ,ipaddr,tcplimit); break; case MAC_ADDRESS: ipt_write( "-A PREROUTING -m mac --mac-source %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n" ,ipaddr,tcplimit); break; case IP_RANGE: ipt_write( "-A PREROUTING -m iprange --src-range %s -p tcp --syn -m connlimit --connlimit-above %s -j DROP\n" ,ipaddr,tcplimit); break; } } } if(atoi(udplimit) > 0){ if (chain == 2) { switch (address_type) { case IP_ADDRESS: ipt_write( "-A PREROUTING -s %s -p udp -m limit --limit %s/sec -j ACCEPT\n" ,ipaddr,udplimit); break; case MAC_ADDRESS: ipt_write( "-A PREROUTING -m mac --mac-source %s -p udp -m limit --limit %s/sec -j ACCEPT\n" ,ipaddr,udplimit); break; case IP_RANGE: ipt_write( "-A PREROUTING -m iprange --src-range %s -p udp -m limit --limit %s/sec -j ACCEPT\n" ,ipaddr,udplimit); break; } } } } free(buf); }
// read nvram into files void new_qoslimit_start(void) { FILE *tc; char *buf; char *g; char *p; char *ibw,*obw;//bandwidth char seq[4];//mark number int iSeq = 10; char *ipaddr_old; char ipaddr[30];//ip address char *dlrate,*dlceil;//guaranteed rate & maximum rate for download char *ulrate,*ulceil;//guaranteed rate & maximum rate for upload char *priority;//priority char *lanipaddr; //lan ip address char *lanmask; //lan netmask char *tcplimit,*udplimit;//tcp connection limit & udp packets per second int priority_num; char *dlr,*dlc,*ulr,*ulc; //download / upload - rate / ceiling int i, address_type; int s[6]; char *waniface; //shibby //qos1 is enable if (!nvram_get_int("new_qoslimit_enable")) return; //read qos1rules from nvram g = buf = strdup(nvram_safe_get("new_qoslimit_rules")); ibw = nvram_safe_get("qos_ibw"); obw = nvram_safe_get("qos_obw"); lanipaddr = nvram_safe_get("lan_ipaddr"); lanmask = nvram_safe_get("lan_netmask"); waniface = nvram_safe_get("wan_iface"); //shibby dlr = nvram_safe_get("qosl_dlr"); //Qos limit download rate dlc = nvram_safe_get("qosl_dlc"); //download ceiling ulr = nvram_safe_get("qosl_ulr"); //upload rate ulc = nvram_safe_get("qosl_ulc"); //upload ceiling if ((tc = fopen(qoslimitfn, "w")) == NULL) return; fprintf(tc, "#!/bin/sh\n" "tc qdisc del dev br0 root 2>/dev/null\n" "tc qdisc del dev %s root 2>/dev/null\n" "\n" "TCA=\"tc class add dev br0\"\n" "TFA=\"tc filter add dev br0\"\n" "TQA=\"tc qdisc add dev br0\"\n" "\n" "SFQ=\"sfq perturb 10\"\n" "\n" "TCAU=\"tc class add dev %s\"\n" "TFAU=\"tc filter add dev %s\"\n" "TQAU=\"tc qdisc add dev %s\"\n" "\n" "tc qdisc add dev br0 root handle 1: htb\n" "tc class add dev br0 parent 1: classid 1:1 htb rate %skbit\n" "\n" "tc qdisc add dev %s root handle 2: htb\n" "tc class add dev %s parent 2: classid 2:1 htb rate %skbit\n" "\n" ,waniface ,waniface ,waniface ,waniface ,ibw ,waniface ,waniface,obw ); if ((nvram_get_int("qosl_enable") == 1) && strcmp(dlr,"") && strcmp(ulr,"")) { if (!strcmp(dlc,"")) strcpy(dlc, dlr); if (!strcmp(ulc,"")) strcpy(ulc, ulr); fprintf(tc, "$TCA parent 1:1 classid 1:100 htb rate %skbit ceil %skbit prio 3\n" "$TQA parent 1:100 handle 100: $SFQ\n" "$TFA parent 1:0 prio 3 protocol ip handle 100 fw flowid 1:100\n" "\n" "$TCAU parent 2:1 classid 2:100 htb rate %skbit ceil %skbit prio 3\n" "$TQAU parent 2:100 handle 100: $SFQ\n" "$TFAU parent 2:0 prio 3 protocol ip handle 100 fw flowid 2:100\n" "\n" ,dlr,dlc ,ulr,ulc); } while (g) { /* ipaddr_old<dlrate<dlceil<ulrate<ulceil<priority<tcplimit<udplimit */ if ((p = strsep(&g, ">")) == NULL) break; i = vstrsep(p, "<", &ipaddr_old, &dlrate, &dlceil, &ulrate, &ulceil, &priority, &tcplimit, &udplimit); if (i!=8) continue; priority_num = atoi(priority); if ((priority_num < 0) || (priority_num > 5)) continue; if (!strcmp(ipaddr_old,"")) continue; address_checker(&address_type, ipaddr_old, ipaddr); sprintf(seq,"%d",iSeq); iSeq++; if (!strcmp(dlceil,"")) strcpy(dlceil, dlrate); if (strcmp(dlrate,"") && strcmp(dlceil, "")) { if (address_type != MAC_ADDRESS) { fprintf(tc, "$TCA parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n" "$TQA parent 1:%s handle %s: $SFQ\n" "$TFA parent 1:0 prio %s protocol ip handle %s fw flowid 1:%s\n" "\n" ,seq,dlrate,dlceil,priority ,seq,seq ,priority,seq,seq); } else if (address_type == MAC_ADDRESS ) { sscanf(ipaddr, "%02X:%02X:%02X:%02X:%02X:%02X",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5]); fprintf(tc, "$TCA parent 1:1 classid 1:%s htb rate %skbit ceil %skbit prio %s\n" "$TQA parent 1:%s handle %s: $SFQ\n" "$TFA parent 1:0 protocol ip prio %s u32 match u16 0x0800 0xFFFF at -2 match u32 0x%02X%02X%02X%02X 0xFFFFFFFF at -12 match u16 0x%02X%02X 0xFFFF at -14 flowid 1:%s\n" "\n" ,seq,dlrate,dlceil,priority ,seq,seq ,priority,s[2],s[3],s[4],s[5],s[0],s[1],seq); } } if (!strcmp(ulceil,"")) strcpy(ulceil, dlrate); if (strcmp(ulrate,"") && strcmp(ulceil, "")) { fprintf(tc, "$TCAU parent 2:1 classid 2:%s htb rate %skbit ceil %skbit prio %s\n" "$TQAU parent 2:%s handle %s: $SFQ\n" "$TFAU parent 2:0 prio %s protocol ip handle %s fw flowid 2:%s\n" "\n" ,seq,ulrate,ulceil,priority ,seq,seq ,priority,seq,seq); } } free(buf); /* shibby - limit br1 */ if (nvram_get_int("limit_br1_enable") == 1) { char *dlr_1,*dlc_1,*ulr_1,*ulc_1,*prio_1; dlr_1 = nvram_safe_get("limit_br1_dlr"); //Qos limit download rate dlc_1 = nvram_safe_get("limit_br1_dlc"); //download ceiling ulr_1 = nvram_safe_get("limit_br1_ulr"); //upload rate ulc_1 = nvram_safe_get("limit_br1_ulc"); //upload ceiling prio_1 = nvram_safe_get("limit_br1_prio"); //priority if (!strcmp(dlc_1,"")) strcpy(dlc_1, dlr_1); if (!strcmp(ulc_1,"")) strcpy(ulc_1, ulr_1); //download for br1 fprintf(tc, "TCA1=\"tc class add dev br1\"\n" "TFA1=\"tc filter add dev br1\"\n" "TQA1=\"tc qdisc add dev br1\"\n" "tc qdisc del dev br1 root\n" "tc qdisc add dev br1 root handle 4: htb\n" "tc class add dev br1 parent 4: classid 4:1 htb rate %skbit\n" "$TCA1 parent 4:1 classid 4:401 htb rate %skbit ceil %skbit prio %s\n" "$TQA1 parent 4:401 handle 401: $SFQ\n" "$TFA1 parent 4:0 prio %s protocol ip handle 401 fw flowid 4:401\n" ,ibw ,dlr_1,dlc_1,prio_1 ,prio_1); //upload from br1 fprintf(tc, "$TCAU parent 2:1 classid 2:501 htb rate %skbit ceil %skbit prio %s\n" "$TQAU parent 2:501 handle 501: $SFQ\n" "$TFAU parent 2:0 prio %s protocol ip handle 501 fw flowid 2:501\n" ,ulr_1,ulc_1,prio_1 ,prio_1); } /* shibby - limit br2 */ if (nvram_get_int("limit_br2_enable") == 1) { char *dlr_2,*dlc_2,*ulr_2,*ulc_2,*prio_2; dlr_2 = nvram_safe_get("limit_br2_dlr"); //Qos limit download rate dlc_2 = nvram_safe_get("limit_br2_dlc"); //download ceiling ulr_2 = nvram_safe_get("limit_br2_ulr"); //upload rate ulc_2 = nvram_safe_get("limit_br2_ulc"); //upload ceiling prio_2 = nvram_safe_get("limit_br2_prio"); //priority if (!strcmp(dlc_2,"")) strcpy(dlc_2, dlr_2); if (!strcmp(ulc_2,"")) strcpy(ulc_2, ulr_2); //download for br2 fprintf(tc, "TCA2=\"tc class add dev br2\"\n" "TFA2=\"tc filter add dev br2\"\n" "TQA2=\"tc qdisc add dev br2\"\n" "tc qdisc del dev br2 root\n" "tc qdisc add dev br2 root handle 6: htb\n" "tc class add dev br2 parent 6: classid 6:1 htb rate %skbit\n" "$TCA2 parent 6:1 classid 6:601 htb rate %skbit ceil %skbit prio %s\n" "$TQA2 parent 6:601 handle 601: $SFQ\n" "$TFA2 parent 6:0 prio %s protocol ip handle 601 fw flowid 6:601\n" ,ibw ,dlr_2,dlc_2,prio_2 ,prio_2); //upload from br2 fprintf(tc, "$TCAU parent 2:1 classid 2:701 htb rate %skbit ceil %skbit prio %s\n" "$TQAU parent 2:701 handle 701: $SFQ\n" "$TFAU parent 2:0 prio %s protocol ip handle 701 fw flowid 2:701\n" ,ulr_2,ulc_2,prio_2 ,prio_2); } /* shibby - limit br3 */ if (nvram_get_int("limit_br3_enable") == 1) { char *dlr_3,*dlc_3,*ulr_3,*ulc_3,*prio_3; dlr_3 = nvram_safe_get("limit_br3_dlr"); //Qos limit download rate dlc_3 = nvram_safe_get("limit_br3_dlc"); //download ceiling ulr_3 = nvram_safe_get("limit_br3_ulr"); //upload rate ulc_3 = nvram_safe_get("limit_br3_ulc"); //upload ceiling prio_3 = nvram_safe_get("limit_br3_prio"); //priority if (!strcmp(dlc_3,"")) strcpy(dlc_3, dlr_3); if (!strcmp(ulc_3,"")) strcpy(ulc_3, ulr_3); //download for br3 fprintf(tc, "TCA3=\"tc class add dev br3\"\n" "TFA3=\"tc filter add dev br3\"\n" "TQA3=\"tc qdisc add dev br3\"\n" "tc qdisc del dev br3 root\n" "tc qdisc add dev br3 root handle 8: htb\n" "tc class add dev br3 parent 8: classid 8:1 htb rate %skbit\n" "$TCA3 parent 8:1 classid 8:801 htb rate %skbit ceil %skbit prio %s\n" "$TQA3 parent 8:801 handle 801: $SFQ\n" "$TFA3 parent 8:0 prio %s protocol ip handle 801 fw flowid 8:801\n" ,ibw ,dlr_3,dlc_3,prio_3 ,prio_3); //upload from br3 fprintf(tc, "$TCAU parent 2:1 classid 2:901 htb rate %skbit ceil %skbit prio %s\n" "$TQAU parent 2:901 handle 901: $SFQ\n" "$TFAU parent 2:0 prio %s protocol ip handle 901 fw flowid 2:901\n" ,ulr_3,ulc_3,prio_3 ,prio_3); } fclose(tc); chmod(qoslimitfn, 0700); //fake start eval((char *)qoslimitfn, "start"); }
// in mangle table void ipt_qos(void) { char *buf; char *g; char *p; char *addr_type, *addr; char *proto; char *port_type, *port; char *class_prio; char *ipp2p, *layer7; char *bcount; char *dscp; char *desc; int class_num; int proto_num; int v4v6_ok; int i; char sport[192]; char saddr[256]; char end[256]; char s[32]; char app[128]; int inuse; const char *chain; unsigned long min; unsigned long max; unsigned long prev_max; int gum; const char *qface; int sizegroup; int class_flag; int rule_num; if (!nvram_get_int("qos_enable")) return; inuse = 0; gum = 0x100; sizegroup = 0; prev_max = 0; rule_num = 0; ip46t_write( ":QOSO - [0:0]\n" "-A QOSO -j CONNMARK --restore-mark --mask 0xff\n" "-A QOSO -m connmark ! --mark 0/0x0f00 -j RETURN\n"); g = buf = strdup(nvram_safe_get("qos_orules")); while (g) { /* addr_type<addr<proto<port_type<port<ipp2p<L7<bcount<dscp<class_prio<desc addr_type: 0 = any 1 = dest ip 2 = src ip 3 = src mac addr: ip/mac if addr_type == 1-3 proto: 0-65535 = protocol -1 = tcp or udp -2 = any protocol port_type: if proto == -1,tcp,udp: d = dest s = src x = both a = any port: port # if proto == -1,tcp,udp bcount: min:max blank = none dscp: empty - any numeric (0:63) - dscp value afXX, csX, be, ef - dscp class class_prio: 0-10 // was 0-8 - Changed from 8 in pkt_sched.h - Toastman -1 = disabled */ if ((p = strsep(&g, ">")) == NULL) break; i = vstrsep(p, "<", &addr_type, &addr, &proto, &port_type, &port, &ipp2p, &layer7, &bcount, &dscp, &class_prio, &desc); rule_num++; if (i == 10) { // fixup < v1.28.XX55 desc = class_prio; class_prio = dscp; dscp = ""; } else if (i == 9) { // fixup < v0.08 // !!! temp desc = class_prio; class_prio = bcount; bcount = ""; dscp = ""; } else if (i != 11) continue; class_num = atoi(class_prio); if ((class_num < 0) || (class_num > 9)) continue; i = 1 << class_num; ++class_num; if ((inuse & i) == 0) { inuse |= i; } v4v6_ok = IPT_V4; #ifdef TCONFIG_IPV6 if (ipv6_enabled()) v4v6_ok |= IPT_V6; #endif class_flag = gum; saddr[0] = '\0'; end[0] = '\0'; // mac or ip address if ((*addr_type == '1') || (*addr_type == '2')) { // match ip v4v6_ok &= ipt_addr(saddr, sizeof(saddr), addr, (*addr_type == '1') ? "dst" : "src", v4v6_ok, (v4v6_ok==IPT_V4), "QoS", desc); if (!v4v6_ok) continue; } else if (*addr_type == '3') { // match mac sprintf(saddr, "-m mac --mac-source %s", addr); // (-m mac modified, returns !match in OUTPUT) } // IPP2P/Layer7 if (ipt_ipp2p(ipp2p, app)) v4v6_ok &= ~IPT_V6; else ipt_layer7(layer7, app); if (app[0]) { v4v6_ok &= ~IPT_V6; // temp: l7 not working either! class_flag = 0x100; // IPP2P and L7 rules may need more than one packet before matching // so port-based rules that come after them in the list can't be sticky // or else these rules might never match. gum = 0; strcat(saddr, app); } // dscp if (ipt_dscp(dscp, s)) { #ifndef LINUX26 v4v6_ok &= ~IPT_V6; // dscp ipv6 match is not present in K2.4 #endif strcat(saddr, s); } // -m connbytes --connbytes x:y --connbytes-dir both --connbytes-mode bytes if (*bcount) { min = strtoul(bcount, &p, 10); if (*p != 0) { strcat(saddr, " -m connbytes --connbytes-mode bytes --connbytes-dir both --connbytes "); ++p; if (*p == 0) { sprintf(saddr + strlen(saddr), "%lu:", min * 1024); } else { max = strtoul(p, NULL, 10); sprintf(saddr + strlen(saddr), "%lu:%lu", min * 1024, (max * 1024) - 1); if (gum) { if (!sizegroup) { // Create table of connbytes sizes, pass appropriate connections there // and only continue processing them if mark was wiped ip46t_write( ":QOSSIZE - [0:0]\n" "-I QOSO 3 -m connmark ! --mark 0/0xff000 -j QOSSIZE\n" "-I QOSO 4 -m connmark ! --mark 0/0xff000 -j RETURN\n"); } if (max != prev_max && sizegroup<255) { class_flag = ++sizegroup << 12; prev_max = max; ip46t_flagged_write(v4v6_ok, "-A QOSSIZE -m connmark --mark 0x%x/0xff000" " -m connbytes --connbytes-mode bytes --connbytes-dir both --connbytes %lu: -j CONNMARK --set-return 0x00000/0xFF\n", (sizegroup << 12), (max * 1024)); #ifdef BCMARM ip46t_flagged_write(v4v6_ok, "-A QOSSIZE -m connmark --mark 0x%x/0xff000" " -m connbytes --connbytes-mode bytes --connbytes-dir both --connbytes %lu: -j RETURN\n", (sizegroup << 12), (max * 1024)); #endif } else { class_flag = sizegroup << 12; } } } } else { bcount = ""; } } chain = "QOSO"; class_num |= class_flag; class_num |= rule_num << 20; sprintf(end + strlen(end), " -j CONNMARK --set-return 0x%x/0xFF\n", class_num); // protocol & ports proto_num = atoi(proto); if (proto_num > -2) { if ((proto_num == 6) || (proto_num == 17) || (proto_num == -1)) { if (*port_type != 'a') { if ((*port_type == 'x') || (strchr(port, ','))) { // dst-or-src port matches, and anything with multiple lists "," use multiport sprintf(sport, "-m multiport --%sports %s", (*port_type == 's') ? "s" : ((*port_type == 'd') ? "d" : ""), port); } else { // single or simple x:y range, use built-in tcp/udp match sprintf(sport, "--%sport %s", (*port_type == 's') ? "s" : ((*port_type == 'd') ? "d" : ""), port); } } else { sport[0] = 0; } if (proto_num != 6) { ip46t_flagged_write(v4v6_ok, "-A %s -p %s %s %s %s", chain, "udp", sport, saddr, end); #ifdef BCMARM ip46t_flagged_write(v4v6_ok, "-A %s -p %s %s %s -j RETURN\n", chain, "udp", sport, saddr); #endif } if (proto_num != 17) { ip46t_flagged_write(v4v6_ok, "-A %s -p %s %s %s %s", chain, "tcp", sport, saddr, end); #ifdef BCMARM ip46t_flagged_write(v4v6_ok, "-A %s -p %s %s %s -j RETURN\n", chain, "tcp", sport, saddr); #endif } } else { ip46t_flagged_write(v4v6_ok, "-A %s -p %d %s %s", chain, proto_num, saddr, end); #ifdef BCMARM ip46t_flagged_write(v4v6_ok, "-A %s -p %d %s -j RETURN\n", chain, proto_num, saddr); #endif } } else { // any protocol ip46t_flagged_write(v4v6_ok, "-A %s %s %s", chain, saddr, end); #ifdef BCMARM ip46t_flagged_write(v4v6_ok, "-A %s %s -j RETURN\n", chain, saddr); #endif } } free(buf); qface = wanfaces.iface[0].name; i = nvram_get_int("qos_default"); if ((i < 0) || (i > 9)) i = 3; // "low" class_num = i + 1; class_num |= 0xFF00000; // use rule_num=255 for default ip46t_write("-A QOSO -j CONNMARK --set-return 0x%x\n", class_num); #ifdef BCMARM ip46t_write("-A QOSO -j RETURN\n"); #endif ipt_write( "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n" "-A FORWARD -o %s -m connmark ! --mark 0 -j CONNMARK --save-mark\n" "-A OUTPUT -o %s -m connmark ! --mark 0 -j CONNMARK --save-mark\n", qface, qface, qface, qface); #ifdef TCONFIG_IPV6 if (*wan6face) { ip6t_write( "-A FORWARD -o %s -j QOSO\n" "-A OUTPUT -o %s -j QOSO\n" "-A FORWARD -o %s -m connmark ! --mark 0 -j CONNMARK --save-mark\n" "-A OUTPUT -o %s -m connmark ! --mark 0 -j CONNMARK --save-mark\n", wan6face, wan6face, wan6face, wan6face); } #endif inuse |= (1 << i) | 1; // default and highest are always built sprintf(s, "%d", inuse); nvram_set("qos_inuse", s); 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; unsigned int rate; unsigned int ceil; // check if we've got a percentage definition in the form of "rate-ceiling" // and that rate > 1 if ((sscanf(p, "%u-%u", &rate, &ceil) == 2) && (rate >= 1)) { ipt_write("-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0xff\n", qface); #ifdef BCMARM ipt_write("-A PREROUTING -i %s -j RETURN\n", qface); #endif #ifdef TCONFIG_IPV6 if (*wan6face) { ip6t_write("-A PREROUTING -i %s -j CONNMARK --restore-mark --mask 0xff\n", wan6face); #ifdef BCMARM ip6t_write("-A PREROUTING -i %s -j RETURN\n", wan6face); #endif } #endif break; } } free(buf); }
void write_to_cfg_node(CLIENT_DETAIL_INFO_TABLE *p_client_tab) { char new_mac[13], *dst_list; char *nv, *nvp, *b = NULL, *search_list = NULL; char *db_mac, *db_user_def, *db_device_name, *db_type, *db_http, *db_printer, *db_itune; FILE *fp = NULL; convert_mac_to_string(p_client_tab->mac_addr[p_client_tab->detail_info_num], new_mac); //Andy Chiu, 2014/10/27. get station list int count = 0; int ret = 0; char *tmpbuf = NULL; NMP_DEBUG("*** write_to_cfg_node: %s ***\n",new_mac); if(nmp_client_list) { search_list = strdup(nmp_client_list); b = strstr(search_list, new_mac); } if(b!=NULL) { //find the client in the DB dst_list = malloc(sizeof(char)*10000); NMP_DEBUG_M("client data in DB: %s\n", new_mac); nvp = nv = b; *(b-1) = '\0'; strcpy(dst_list, search_list); NMP_DEBUG_M("dst_list= %s\n", dst_list); //b++; while (nv && (b = strsep(&nvp, "<")) != NULL) { if (b == NULL) continue; if (vstrsep(b, ">", &db_mac, &db_user_def, &db_device_name, &db_type, &db_http, &db_printer, &db_itune) != 7) continue; NMP_DEBUG_M("%s,%s,%d,%d,%d,%d\n", db_mac, db_user_def, db_device_name, atoi(db_type), atoi(db_http), atoi(db_printer), atoi(db_itune)); if (!strcmp(p_client_tab->device_name[p_client_tab->detail_info_num], db_device_name) && p_client_tab->type[p_client_tab->detail_info_num] == atoi(db_type) && p_client_tab->http[p_client_tab->detail_info_num] == atoi(db_http) && p_client_tab->printer[p_client_tab->detail_info_num] == atoi(db_printer) && p_client_tab->itune[p_client_tab->detail_info_num] == atoi(db_itune) ) { NMP_DEBUG("DATA the same!\n"); return; } sprintf(dst_list, "%s<%s<%s", dst_list, db_mac, db_user_def); if (strcmp(p_client_tab->device_name[p_client_tab->detail_info_num], "")) { NMP_DEBUG("Update device name: %s.\n", p_client_tab->device_name[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%s", dst_list, p_client_tab->device_name[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_device_name); if (p_client_tab->type[p_client_tab->detail_info_num] != 6) { client_updated = 1; NMP_DEBUG("Update type: %d\n", p_client_tab->type[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->type[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_type); if (!strcmp(db_http, "0") ) { client_updated = 1; NMP_DEBUG("Update http: %d\n", p_client_tab->http[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->http[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_http); if (!strcmp(db_printer, "0") ) { client_updated = 1; NMP_DEBUG("Update type: %d\n", p_client_tab->printer[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->printer[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_printer); if (!strcmp(db_itune, "0")) { client_updated = 1; NMP_DEBUG("Update type: %d\n", p_client_tab->itune[p_client_tab->detail_info_num]); sprintf(dst_list, "%s>%d", dst_list, p_client_tab->itune[p_client_tab->detail_info_num]); } else sprintf(dst_list, "%s>%s", dst_list, db_itune); if(nvp != NULL) { strcat(dst_list, "<"); strcat(dst_list, nvp); } //Andy Chiu, 2014/10/22. Fix memory leak SAFE_FREE(nmp_client_list); nmp_client_list = strdup(dst_list); SAFE_FREE(dst_list); NMP_DEBUG_M("*** Update nmp_client_list:\n%s\n", nmp_client_list); write_to_file(nmp_client_path, nmp_client_list, strlen(nmp_client_list), "w"); //nvram_set("nmp_client_list", nmp_client_list); break; } } else { //new client NMP_DEBUG_M("new client: %d-%s,%s,%d\n",p_client_tab->detail_info_num, new_mac, p_client_tab->device_name[p_client_tab->detail_info_num], p_client_tab->type[p_client_tab->detail_info_num]); tmpbuf = malloc(10000); if(!tmpbuf) { NMP_DEBUG("[%s, %d]Can't alloc memory\n", __FUNCTION__, __LINE__); return; } //sprintf(nmp_client_list,"%s<%s>>%s>%d>%d>%d>%d", nmp_client_list, sprintf(tmpbuf,"%s<%s>>%s>%d>%d>%d>%d", nmp_client_list? nmp_client_list: "", new_mac, p_client_tab->device_name[p_client_tab->detail_info_num], p_client_tab->type[p_client_tab->detail_info_num], p_client_tab->http[p_client_tab->detail_info_num], p_client_tab->printer[p_client_tab->detail_info_num], p_client_tab->itune[p_client_tab->detail_info_num] ); SAFE_FREE(nmp_client_list); nmp_client_list = strdup(tmpbuf); SAFE_FREE(tmpbuf); //nvram_set("nmp_client_list", nmp_client_list); NMP_DEBUG("[%s, %d]\n", __FUNCTION__, __LINE__); write_to_file(nmp_client_path, nmp_client_list, strlen(nmp_client_list), "w"); NMP_DEBUG("[%s, %d]\n", __FUNCTION__, __LINE__); } SAFE_FREE(search_list); //Andy Chiu, 2014/10/27. update the cfg_node int i; char buf[128]; fp = fopen(cl_path, "w"); //Andy Chiu, 2014/12/03 count = 0; for(i = 0; i < 255; ++i) { if(p_client_tab->exist[i]) //item exist { char attr[64]; char buf[256]; sprintf(buf, "<%d.%d.%d.%d>%02x:%02x:%02x:%02x:%02x:%02x>%s>%d>%d>%d>%d", p_client_tab->ip_addr[i][0], p_client_tab->ip_addr[i][1], p_client_tab->ip_addr[i][2], p_client_tab->ip_addr[i][3], p_client_tab->mac_addr[i][0], p_client_tab->mac_addr[i][1] , p_client_tab->mac_addr[i][2], p_client_tab->mac_addr[i][3], p_client_tab->mac_addr[i][4], p_client_tab->mac_addr[i][5], p_client_tab->device_name[i], p_client_tab->type[i], p_client_tab->http[i], p_client_tab->printer[i], p_client_tab->itune[i]); sprintf(attr, "dev%d", count); // ret = tcapi_set("ClientList_Entry", attr, buf); // if(ret) // NMP_DEBUG_M("set device(%d) failed!(%d)(%s)\n", count, ret, buf); if(fp) //Andy Chiu, 2014/12/03 fwrite(buf, sizeof(char), strlen(buf), fp); ++count; } if( count >= p_client_tab->detail_info_num + 1) break; } if(fp) //Andy Chiu, 2014/12/03 fclose(fp); sprintf(buf, "%d", p_client_tab->detail_info_num + 1); ret = tcapi_set("ClientList_Common", "size", buf); if(ret) NMP_DEBUG_M("set ClientList_Common:size failed!\n"); NMP_DEBUG_M("new client list size is %d\n", p_client_tab->detail_info_num + 1); }
int add_iQosRules(char *pcWANIF) { char *buf; char *g; char *p; char *addr_type, *addr; char *proto; char *port_type, *port; char *class_prio; char *ipp2p, *layer7; char *bcount; int class_num; int proto_num; int i; char s[256]; int inuse; int qosox_enable; unsigned long min; int bcount_enable; int method; int gum; int sticky_enable; char acClass[8]; char acByteCounter[32]; EVAL_CMD stIptCommand = { 3, { "iptables", "-t", "mangle", NULL, } }; if (pcWANIF == NULL || !nvram_match("qos_enable", "1")) return -1; printf("\n%s: %s", __FUNCTION__, pcWANIF); qosox_enable = bcount_enable = inuse = sticky_enable = 0; method = atoi(nvram_safe_get("qos_method")); // strict rule ordering gum = (method == 0) ? 0x100 : 0; if (nvram_match("qos_sticky", "0")) sticky_enable = 1; eval("iptables", "-t", "mangle", "-N", "QOSO"); eval("iptables", "-t", "mangle", "-A", "QOSO", "-j", "CONNMARK", "--restore-mark", "--mask", "0xff"); eval("iptables", "-t", "mangle", "-A", "QOSO", "-m", "connmark", "!", "--mark", "0/0xff00", "-j", "RETURN"); g = buf = strdup(nvram_safe_get("qos_orules")); while (g) { /* addr_type<addr<proto<port_type<port<<<<desc addr_type: 0 = any 1 = dest ip 2 = src ip 3 = src mac addr: ip/mac if addr_type == 1-3 proto: 0-65535 = protocol -1 = tcp or udp -2 = any protocol port_type: if proto == -1,tcp,udp: d = dest s = src x = both a = any port: port # if proto == -1,tcp,udp class_prio: 0-4, 0 being highest */ if ((p = strsep(&g, ">")) == NULL) break; i = vstrsep(p, "<", &addr_type, &addr, &proto, &port_type, &port, &ipp2p, &layer7, &bcount, &class_prio, &p); if (i == 9) { class_prio = bcount; bcount = NULL; } else if (i != 10) continue; class_num = atoi(class_prio); if ((class_num < 0) || (class_num > 4)) continue; i = 1 << class_num++; if (method == 1) class_num |= 0x200; if ((inuse & i) == 0) { inuse |= i; printf("inuse=%d\n", inuse); } /* Beginning of the Rule */ { stIptCommand.siCount = 3; stIptCommand.apCommand[stIptCommand.siCount++] = "-A"; if (qosox_enable) stIptCommand.apCommand[stIptCommand.siCount++] = "QOSOX"; //Offset 4 else stIptCommand.apCommand[stIptCommand.siCount++] = "QOSO"; } /* * protocol & ports: */ { proto_num = atoi(proto); if (proto_num > -2) { stIptCommand.apCommand[stIptCommand.siCount++] = "-p"; if (proto_num == 17) stIptCommand.apCommand[stIptCommand.siCount++] = "udp"; //Offset 6 else if (proto_num != -1) stIptCommand.apCommand[stIptCommand.siCount++] = proto; else stIptCommand.apCommand[stIptCommand.siCount++] = "tcp"; //Offset 6 if ((proto_num == 6) || (proto_num == 17) || (proto_num == -1)) { if (*port_type != 'a') { if ((*port_type == 'x') || (strchr(port, ','))) { // dst-or-src port matches, and anything with multiple lists "," use mport stIptCommand.apCommand[stIptCommand.siCount++] = "-m"; stIptCommand.apCommand[stIptCommand.siCount++] = "mport"; if (*port_type == 's') stIptCommand.apCommand[stIptCommand.siCount++] = "--sports"; else stIptCommand.apCommand[stIptCommand.siCount++] = "--dports"; } else { if (*port_type == 's') stIptCommand.apCommand[stIptCommand.siCount++] = "--sport"; else if (*port_type == 'd') stIptCommand.apCommand[stIptCommand.siCount++] = "--dport"; else stIptCommand.apCommand[stIptCommand.siCount++] = "--port"; } if (port && *port) stIptCommand.apCommand[stIptCommand.siCount++] = port; } } } } /* * MAC or IP address match: */ { if ((*addr_type == '1') || (*addr_type == '2')) { // match ip if (strchr(addr, '-') != NULL) { stIptCommand.apCommand[stIptCommand.siCount++] = "-m"; stIptCommand.apCommand[stIptCommand.siCount++] = "iprange"; if (*addr_type == '1') stIptCommand.apCommand[stIptCommand.siCount++] = "--dst-range"; else stIptCommand.apCommand[stIptCommand.siCount++] = "--src-range"; } else { if (*addr_type == '1') stIptCommand.apCommand[stIptCommand.siCount++] = "-d"; else stIptCommand.apCommand[stIptCommand.siCount++] = "-s"; } } else if (*addr_type == '3') { // match mac stIptCommand.apCommand[stIptCommand.siCount++] = "-m"; stIptCommand.apCommand[stIptCommand.siCount++] = "mac"; stIptCommand.apCommand[stIptCommand.siCount++] = "--mac-source"; } if (*addr_type != '0') stIptCommand.apCommand[stIptCommand.siCount++] = addr; } /* End of the rule */ { class_num |= gum; if (sticky_enable) class_num &= 0xFF; sprintf(acClass, "0x%x/0xFF", class_num); stIptCommand.apCommand[stIptCommand.siCount++] = "-j"; stIptCommand.apCommand[stIptCommand.siCount++] = "CONNMARK"; stIptCommand.apCommand[stIptCommand.siCount++] = "--set-mark"; stIptCommand.apCommand[stIptCommand.siCount++] = acClass; stIptCommand.apCommand[stIptCommand.siCount++] = NULL; } printcmd(&stIptCommand); _eval(stIptCommand.apCommand, NULL, 4, NULL); if (proto_num == -1) { stIptCommand.apCommand[6] = "udp"; printcmd(&stIptCommand); _eval(stIptCommand.apCommand, NULL, 4, NULL); } stIptCommand.siCount = 3; stIptCommand.apCommand[stIptCommand.siCount++] = "-A"; if(qosox_enable) stIptCommand.apCommand[stIptCommand.siCount++] = "QOSOX"; else stIptCommand.apCommand[stIptCommand.siCount++] = "QOSO"; stIptCommand.apCommand[stIptCommand.siCount++] = "-j"; stIptCommand.apCommand[stIptCommand.siCount++] = "RETURN"; stIptCommand.apCommand[stIptCommand.siCount++] = NULL; printcmd(&stIptCommand); _eval(stIptCommand.apCommand, NULL, 4, NULL); } free(buf); /* * The default class: */ { char acClass[4]; i = atoi(nvram_safe_get("qos_default")); if ((i < 0) || (i > 9)) i = 3; // "low" class_num = i + 1; if (method == 1) class_num |= 0x200; sprintf(acClass, "0x%x", class_num); eval("iptables", "-t", "mangle", "-A", qosox_enable ? "QOSOX" : "QOSO", "-j", "CONNMARK", "--set-mark", acClass); eval("iptables", "-t", "mangle", "-A", qosox_enable ? "QOSOX" : "QOSO", "-j", "RETURN"); } eval("iptables", "-t", "mangle", "-A", "FORWARD", "-o", pcWANIF, "-j", qosox_enable ? "QOSOX" : "QOSO"); /* * Ingress rules: */ { i = atoi(nvram_safe_get("qos_default")); inuse |= (1 << i) | 1; // default and highest are always built sprintf(s, "%d", inuse); nvram_set("qos_inuse", s); // create the inuse NVRAM here g = buf = strdup(nvram_safe_get("qos_irates")); for (i = 0; i < 5; i++) { if ((!g) || ((p = strsep(&g, ",")) == NULL)) continue; if ((inuse & (1 << i)) == 0) continue; if (atoi(p) > 0) {// if ibound rules are set, use the PRE-ROUTE eval("iptables", "-t", "mangle", "-A", "PREROUTING", "-i", pcWANIF, "-j", "CONNMARK", "--restore-mark", "--mask", "0xff"); break; } } free(buf); } }
void ipt_restrictions(void) { char buf[8192]; char *p, *q; int n; char *comps, *matches, *http; int nrule; int blockall; char reschain[32]; char devchain[32]; char nextchain[32]; int need_web; char *pproto; char *dir; char *pport; int proto; char *ipp2p; char *layer7; char *addr_type, *addr; char app[256]; char ports[256]; char iptaddr[192]; int http_file; int ex; int first; int v4v6_ok; need_web = 0; first = 1; nvram_unset("rrules_timewarn"); nvram_set("rrules_radio", "-1"); unsched_restrictions(); for (nrule = 0; nrule < MAX_NRULES; ++nrule) { sprintf(buf, "rrule%d", nrule); if ((p = nvram_get(buf)) == NULL) continue; if (strlen(p) >= sizeof(buf)) continue; strcpy(buf, p); if ((vstrsep(buf, "|", &q, // 0/1 &p, &p, &p, // time (ignored) &comps, // &matches, // &http, // &p // http file match ) != 8) || (*q != '1')) continue; http_file = atoi(p); if (comps[0] == '~') { // a wireless disable rule, skip continue; } if (first) { first = 0; ip46t_write(":restrict - [0:0]\n"); #ifdef TCONFIG_IPV6 if (*wan6face) ip6t_write("-A FORWARD -o %s -j restrict\n", wan6face); #endif for (n = 0; n < wanfaces.count; ++n) { if (*(wanfaces.iface[n].name)) { ipt_write("-A FORWARD -o %s -j restrict\n", wanfaces.iface[n].name); } } // Only mess with DNS requests that are coming in on INPUT ip46t_write("-I INPUT 1 ! -i lo -p udp --dport 53 -j restrict\n"); } sprintf(reschain, "rres%02d", nrule); ip46t_write(":%s - [0:0]\n", reschain); blockall = 1; while ((q = strsep(&matches, ">")) != NULL) { n = vstrsep(q, "<", &pproto, &dir, &pport, &ipp2p, &layer7, &addr_type, &addr); if (n == 5) { // fixup for backward compatibility addr_type = "0"; } else if (n != 7) continue; if ((*dir != 'a') && (*dir != 's') && (*dir != 'd') && (*dir != 'x')) continue; // p2p, layer7 if (!ipt_ipp2p(ipp2p, app)) { if (ipt_layer7(layer7, app) == -1) continue; } #ifdef TCONFIG_IPV6 v4v6_ok = ((*app) ? 0 : IPT_V6) | IPT_V4; #else v4v6_ok = IPT_V4; #endif // dest ip/domain address if ((*addr_type == '1') || (*addr_type == '2')) { v4v6_ok = ipt_addr(iptaddr, sizeof(iptaddr), addr, (*addr_type == '1') ? "dst" : "src", v4v6_ok, (v4v6_ok == IPT_V4), "restrictions", NULL); if (!v4v6_ok) continue; } else { iptaddr[0] = 0; } blockall = 0; // proto & ports proto = atoi(pproto); if (proto <= -2) { // shortcut if any proto+any port ip46t_flagged_write(v4v6_ok, "-A %s %s %s -j %s\n", reschain, iptaddr, app, chain_out_drop); continue; } else if ((proto == 6) || (proto == 17) || (proto == -1)) { if ((*dir != 'a') && (*pport)) { if ((*dir == 'x') || (strchr(pport, ','))) { // use multiport for multiple ports or src-or-dst type matches snprintf(ports, sizeof(ports), "-m multiport --%sports %s", (*dir == 'x') ? "" : dir, pport); } else { // else, use built-in snprintf(ports, sizeof(ports), "--%sport %s", dir, pport); } } else { ports[0] = 0; } if (proto != 17) ip46t_flagged_write(v4v6_ok, "-A %s -p tcp %s %s %s -j %s\n", reschain, ports, iptaddr, app, chain_out_drop); if (proto != 6) ip46t_flagged_write(v4v6_ok, "-A %s -p udp %s %s %s -j %s\n", reschain, ports, iptaddr, app, chain_out_drop); } else { ip46t_flagged_write(v4v6_ok, "-A %s -p %d %s %s -j %s\n", reschain, proto, iptaddr, app, chain_out_drop); } } // p = http; while (*p) { if ((*p == '\t') || (*p == '\r') || (*p == '\n') || (*p == '"')) *p = ' '; ++p; } while ((n = strlen(http)) > 0) { if (n >= 511) { p = http + 510; while ((p > http) && (*p != ' ')) --p; if (p <= http) { // too long break; } *p = 0; } else p = NULL; ip46t_write("-A %s -p tcp -m web --hore \"%s\" -j %s\n", reschain, http, chain_out_reject); need_web = 1; blockall = 0; if (p == NULL) break; http = p + 1; } // app[0] = 0; if (http_file & 1) strcat(app, ".ocx$ .cab$ "); if (http_file & 2) strcpy(app, ".swf$ "); if (http_file & 4) strcat(app, ".class$ .jar$"); if (app[0]) { ip46t_write("-A %s -p tcp -m multiport --dports %s -m web --path \"%s\" -j %s\n", reschain, nvram_safe_get("rrulewp"), app, chain_out_reject); need_web = 1; blockall = 0; } if (*comps) { if (blockall) { ip46t_write("-X %s\n", reschain); // chain not needed sprintf(nextchain, "-j %s", chain_out_drop); } else { sprintf(nextchain, "-g %s", reschain); } ex = 0; sprintf(devchain, "rdev%02d", nrule); ip46t_write(":%s - [0:0]\n", devchain); while ((q = strsep(&comps, ">")) != NULL) { if (*q == 0) continue; if (*q == '!') { ex = 1; continue; } #ifdef TCONFIG_IPV6 v4v6_ok = IPT_V6 | IPT_V4; #else v4v6_ok = IPT_V4; #endif if (sscanf(q, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", iptaddr, iptaddr, iptaddr, iptaddr, iptaddr, iptaddr) == 6) { snprintf(iptaddr, sizeof(iptaddr), "-m mac --mac-source %s", q); } else { v4v6_ok = ipt_addr(iptaddr, sizeof(iptaddr), q, "src", v4v6_ok, (v4v6_ok == IPT_V4), "restrictions", "filtering"); if (!v4v6_ok) continue; } ip46t_flagged_write(v4v6_ok, "-A %s %s %s\n", devchain, iptaddr, ex ? "-j RETURN" : nextchain); } if (ex) { ip46t_write("-A %s %s\n", devchain, nextchain); } } else if (blockall) { ip46t_write("-A %s -j %s\n", reschain, chain_out_drop); } } nvram_set("rrules_activated", "0"); if (need_web) modprobe("ipt_web"); }
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; }
static int start_bandwidth_limiter(void) { FILE *f = NULL; char *buf, *g, *p; char *enable, *addr, *dlc, *upc, *prio; int class = 0; int s[6]; // strip mac address int addr_type; char addr_new[30]; if ((f = fopen(qosfn, "w")) == NULL) return -2; fprintf(f, "#!/bin/sh\n" "WAN=%s\n" "tc qdisc del dev $WAN root 2>/dev/null\n" "tc qdisc del dev $WAN ingress 2>/dev/null\n" "tc qdisc del dev br0 root 2>/dev/null\n" "tc qdisc del dev br0 ingress 2>/dev/null\n" "\n" "TQAU=\"tc qdisc add dev $WAN\"\n" "TCAU=\"tc class add dev $WAN\"\n" "TFAU=\"tc filter add dev $WAN\"\n" "SFQ=\"sfq perturb 10\"\n" "TQA=\"tc qdisc add dev br0\"\n" "TCA=\"tc class add dev br0\"\n" "TFA=\"tc filter add dev br0\"\n" "\n" "$TQA root handle 1: htb\n" "$TCA parent 1: classid 1:1 htb rate 1024000kbit\n" "\n" "$TQAU root handle 2: htb\n" "$TCAU parent 2: classid 2:1 htb rate 1024000kbit\n" , get_wan_ifname(0) ); /* 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 */ 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; address_checker(&addr_type, addr, addr_new); class = atoi(prio) + 10; if (addr_type == TYPE_MAC) { sscanf(addr_new, "%02X:%02X:%02X:%02X:%02X:%02X",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5]); fprintf(f, "\n" "$TCA parent 1:1 classid 1:%d htb rate %skbit ceil %skbit prio %s\n" "$TQA parent 1:%d handle %d: $SFQ\n" "$TFA parent 1: protocol ip prio %s u32 match u16 0x0800 0xFFFF at -2 match u32 0x%02X%02X%02X%02X 0xFFFFFFFF at -12 match u16 0x%02X%02X 0xFFFF at -14 flowid 1:%d" "\n" "$TCAU parent 2:1 classid 2:%d htb rate %skbit ceil %skbit prio %s\n" "$TQAU parent 2:%d handle %d: $SFQ\n" "$TFAU parent 2: prio %s protocol ip handle %d fw flowid 2:%d\n" , class, dlc, dlc, prio , class, class , prio, s[2], s[3], s[4], s[5], s[0], s[1], class , class, upc, upc, prio , class, class , prio, class, class ); } else if (addr_type == TYPE_IP || addr_type == TYPE_IPRANGE)
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; }
void ipt_forward(ipt_table_t table) { char *nv, *nvp, *b; const char *proto, *saddr, *xports, *iport, *iaddr, *desc; const char *c; const char *mdport; int i, n; char ip[64]; char src[64]; nvp = nv = strdup(nvram_safe_get("portforward")); if (!nv) return; while ((b = strsep(&nvp, ">")) != NULL) { /* [<1.01] 1<3<30,40-45<60<5<desc [<1.07] 1<3<30,40-45<60<192.168.1.5<desc 1<3<71.72.73.74<30,40-45<60<192.168.1.5<desc 1 = enabled 3 = tcp & udp 71.72.73.74 = src addr 30,40-45 = ext port 60 = int port 192.168.1.5 = dst addr desc = desc */ n = vstrsep(b, "<", &c, &proto, &saddr, &xports, &iport, &iaddr, &desc); if ((n < 6) || (*c != '1')) continue; if (n == 6) { // <1.07 desc = iaddr; iaddr = iport; iport = xports; xports = saddr; saddr = ""; } if (!ipt_addr(src, sizeof(src), saddr, "src", IPT_V4, 1, "IPv4 port forwarding", desc)) continue; if (strchr(iaddr, '.') == NULL && strtol(iaddr, NULL, 10) > 0) { // < 1.01: 5 -> 192.168.1.5 strcpy(ip, lan_cclass); strlcat(ip, iaddr, sizeof(ip)); } else { if (host_addrtypes(iaddr, IPT_V4) != IPT_V4) { ipt_log_unresolved(iaddr, "IPv4", "IPv4 port forwarding", desc); continue; } strlcpy(ip, iaddr, sizeof(ip)); } mdport = (strchr(xports, ',') != NULL) ? "-m multiport --dports" : "--dport"; for (i = 0; i < 2; ++i) { if ((1 << i) & (*proto - '0')) { c = tcpudp[i]; if (table == IPT_TABLE_NAT) { ipt_write("-A %s -p %s %s %s %s -j DNAT --to-destination %s%s%s\n", chain_wan_prerouting, c, src, mdport, xports, ip, *iport ? ":" : "", iport); if (nvram_get_int("nf_loopback") == 1) { for (n = 0; n < wanfaces.count; ++n) { if (*(wanfaces.iface[n].name)) { ipt_write("-A POSTROUTING -p %s %s %s -s %s/%s -d %s -j SNAT --to-source %s\n", c, mdport, *iport ? iport : xports, nvram_safe_get("lan_ipaddr"), // corrected by ipt nvram_safe_get("lan_netmask"), ip, wanfaces.iface[n].ip); } } } } else { // filter ipt_write("-A wanin %s -p %s -m %s -d %s %s %s -j %s\n", src, c, c, ip, mdport, *iport ? iport : xports, chain_in_accept); } } } } free(nv); }