Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;

}
Beispiel #6
0
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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
// 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("/");
}
Beispiel #9
0
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;
}
Beispiel #10
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);	
	}

}
Beispiel #11
0
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");
}
Beispiel #12
0
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);
}
Beispiel #13
0
// 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");
}
Beispiel #14
0
// 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);
}
Beispiel #15
0
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);
}
Beispiel #16
0
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);
	}

}
Beispiel #17
0
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");
}
Beispiel #18
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;
}
Beispiel #19
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)
Beispiel #20
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;
}
Beispiel #21
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);
}