gargoyle: cleanup build warning and makefile

This commit is contained in:
AmadeusGhost 2021-11-04 23:15:14 +08:00
parent 418beef4bc
commit b613d40f8d
10 changed files with 236 additions and 392 deletions

View File

@ -1,48 +1,38 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gargoyle-firewall-util
PKG_VERSION:=$(GARGOYLE_VERSION)
ifeq ($(GARGOYLE_VERSION),)
PKG_VERSION:=1.0.0
endif
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_MAINTAINER:=Eric Bishop <eric@gargoyle-router.com>
include $(INCLUDE_DIR)/package.mk
define Package/gargoyle-firewall-util
SECTION:=net
CATEGORY:=Network
TITLE:=A couple of shell script routines for firewall initialization
DEPENDS:=+ebtables +libericstools +uci +libiptbwctl +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra +iptables-mod-nat-extra +iptables-mod-extra +iptables-mod-iprange +iptables-mod-bandwidth +iptables-mod-timerange +iptables-mod-weburl +kmod-gre +kmod-pptp +kmod-tun +kmod-nf-nathelper +kmod-nf-nathelper-extra
MAINTAINER:=Eric Bishop <eric@gargoyle-router.com>
SECTION:=net
CATEGORY:=Network
TITLE:=A couple of shell script routines for firewall initialization
DEPENDS:=+ebtables +libericstools +libiptbwctl +iptables-mod-filter +iptables-mod-ipopt \
+iptables-mod-conntrack-extra +iptables-mod-nat-extra +iptables-mod-extra +iptables-mod-iprange \
+iptables-mod-bandwidth +iptables-mod-timerange +iptables-mod-weburl +kmod-gre +kmod-nf-nathelper \
+kmod-nf-nathelper-extra +kmod-pptp +kmod-tun +uci
endef
define Package/gargoyle-firewall-util/description
A couple of shell script routines for firewall initialization
endef
define Build/Prepare
echo PACKAGE BUILD DIR = $(PACKAGE_BUILD_DIR)
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
A couple of shell script routines for firewall initialization
endef
define Build/Configure
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
STAGING_DIR="$(STAGING_DIR)" \
CFLAGS="$(TARGET_CFLAGS) -I $(STAGING_DIR)/usr/include" \
LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib"
LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib"
endef
define Package/gargoyle-firewall-util/postinst
included=$$(cat $${IPKG_INSTROOT}/etc/config/firewall | grep 'gargoyle_additions.firewall' )
if [ -z "$$included" ] ; then printf "config include\n\toption type script\n\toption path /usr/lib/gargoyle_firewall_util/gargoyle_additions.firewall\n\toption family IPv4\n\toption reload 1\n\n" >> $${IPKG_INSTROOT}/etc/config/firewall ; fi
@ -54,19 +44,18 @@ define Package/gargoyle-firewall-util/install
$(INSTALL_DIR) $(1)/usr/bin/
$(INSTALL_DIR) $(1)/etc/init.d/
$(INSTALL_DIR) $(1)/etc/ppp/ip-up.d/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/make_iptables_rules $(1)/usr/bin/make_iptables_rules
$(INSTALL_BIN) $(PKG_BUILD_DIR)/delete_chain_from_table $(1)/usr/bin/delete_chain_from_table
$(INSTALL_BIN) $(PKG_BUILD_DIR)/backup_quotas $(1)/usr/bin/backup_quotas
$(INSTALL_BIN) $(PKG_BUILD_DIR)/restore_quotas $(1)/usr/bin/restore_quotas
$(INSTALL_BIN) $(PKG_BUILD_DIR)/print_quotas $(1)/usr/bin/print_quotas
$(INSTALL_BIN) ./files/gargoyle_firewall_util.sh $(1)/usr/lib/gargoyle_firewall_util/gargoyle_firewall_util.sh
$(INSTALL_BIN) ./files/gargoyle_additions.firewall $(1)/usr/lib/gargoyle_firewall_util/gargoyle_additions.firewall
$(INSTALL_BIN) ./files/gargoyle_additions.firewall $(1)/usr/lib/gargoyle_firewall_util/gargoyle_additions.firewall
$(INSTALL_BIN) ./files/gargoyle_firewall.hotplug $(1)/etc/hotplug.d/iface/21-gargoyle_firewall
$(INSTALL_BIN) ./files/set_kernel_timezone.init $(1)/etc/init.d/set_kernel_timezone
$(INSTALL_BIN) ./files/modemaccess.pppoe $(1)/etc/ppp/ip-up.d/modemaccess.sh
$(INSTALL_BIN) ./files/modemaccess.pppoe $(1)/etc/ppp/ip-up.d/modemaccess.sh
endef
$(eval $(call BuildPackage,gargoyle-firewall-util))

View File

@ -18,7 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -35,13 +34,13 @@ void backup_quota(char* quota_id, char* quota_backup_dir);
char* get_uci_option(struct uci_context* ctx,char* package_name, char* section_name, char* option_name);
char* get_option_value_string(struct uci_option* uopt);
int main(void)
{
struct uci_context *ctx = uci_alloc_context();
list* quota_sections = get_all_sections_of_type(ctx, "firewall", "quota");
system("mkdir -p /usr/data/quotas");
unlock_bandwidth_semaphore_on_exit();
while(quota_sections->length > 0)
{
char* next_quota = shift_list(quota_sections);
@ -59,10 +58,10 @@ int main(void)
if(do_backup)
{
//do backup
/* base id for quota is the ip associated with it*/
char* backup_id = get_uci_option(ctx, "firewall", next_quota, "id");
char* ip = get_uci_option(ctx, "firewall", next_quota, "ip");
char* ip = get_uci_option(ctx, "firewall", next_quota, "ip");
if(ip == NULL)
{
ip = strdup("ALL");
@ -82,7 +81,6 @@ int main(void)
backup_id = strdup(ip);
}
char* types[] = { "ingress_limit", "egress_limit", "combined_limit" };
char* postfixes[] = { "_ingress", "_egress", "_combined" };
int type_index;
@ -92,7 +90,7 @@ int main(void)
if(defined != NULL)
{
char* type_id = dynamic_strcat(2, backup_id, postfixes[type_index]);
backup_quota(type_id, "/usr/data/quotas" );
free(type_id);
@ -105,7 +103,7 @@ int main(void)
}
free(next_quota);
}
unsigned long num;
destroy_list(quota_sections, DESTROY_MODE_FREE_VALUES, &num);
uci_free_context(ctx);
@ -136,8 +134,8 @@ list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* sec
void backup_quota(char* id, char* quota_backup_dir)
{
/* if we ever bother to allow quotas to apply to subnets
* specified with '/', this may be necessary
/* if we ever bother to allow quotas to apply to subnets
* specified with '/', this may be necessary
*/
char* quota_file_name;
if(strstr(id, "/") != NULL)
@ -150,7 +148,7 @@ void backup_quota(char* id, char* quota_backup_dir)
}
char* quota_file_path = dynamic_strcat(3, quota_backup_dir, "/quota_", quota_file_name);
unsigned long num_ips;
ip_bw *ip_buf = NULL;
int query_succeeded = get_all_bandwidth_usage_for_rule_id(id, &num_ips, &ip_buf, 5000);
@ -160,7 +158,7 @@ void backup_quota(char* id, char* quota_backup_dir)
free(ip_buf);
}
free(quota_file_path);
free(quota_file_name);
free(quota_file_name);
}
char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_name, char* option_name)
@ -186,9 +184,6 @@ char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_
return option_value;
}
// this function dynamically allocates memory for
// the option string, but since this program exits
// almost immediately (after printing variable info)
@ -224,5 +219,3 @@ char* get_option_value_string(struct uci_option* uopt)
return opt_str;
}

View File

@ -5,6 +5,7 @@
#include <sys/types.h>
#include <erics_tools.h>
#define malloc safe_malloc
#define strdup safe_strdup
@ -24,13 +25,11 @@ int main(int argc, char **argv)
unsigned long num_lines = 0;
char** table_dump = get_shell_command_output_lines(command, &num_lines);
free(command);
unsigned long line_index;
char* current_chain = NULL;
list* delete_commands = initialize_list();
for(line_index=0; line_index < num_lines; line_index++)
{
char* line = table_dump[line_index];
@ -42,7 +41,7 @@ int main(int argc, char **argv)
if(current_chain != NULL) { free(current_chain); }
current_chain = strdup(line_pieces[1]);
}
else
else
{
unsigned long line_num;
int read = sscanf(line_pieces[0], "%ld", &line_num);
@ -61,7 +60,7 @@ int main(int argc, char **argv)
free_null_terminated_string_array(line_pieces);
}
free_null_terminated_string_array(table_dump);
/* final two commands to flush chain being deleted and whack it */
unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -F ", delete_chain, " 2>/dev/null"));
unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -X ", delete_chain, " 2>/dev/null"));
@ -76,4 +75,3 @@ int main(int argc, char **argv)
return 0;
}

View File

@ -29,6 +29,7 @@
#include <erics_tools.h>
#include <uci.h>
#define malloc safe_malloc
#define strdup safe_strdup
@ -114,17 +115,17 @@ int main(int argc, char **argv)
if(def != NULL)
{
char** rules = compute_rules(def, table, chain, 0, target, target_options);
int rindex = 0;
for(rindex=0; rules[rindex] != NULL; rindex++)
{
{
if(run_commands == 0)
{
printf("%s\n", rules[rindex]);
}
else
{
system(rules[rindex]);
system(rules[rindex]);
}
}
}
@ -140,18 +141,13 @@ int main(int argc, char **argv)
}
return 0;
}
/*
/*
* Note we've currently maxed out out one whole byte of address space
* in the connmark at this point. If we want to match in
* further dimensions, we will have to be greedy and take
* further dimensions, we will have to be greedy and take
* even more address space
*/
char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingress, char* target, char* target_options)
@ -163,7 +159,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
target = strdup(target);
to_uppercase(target);
/* get timerange vars first */
char* active_hours = get_map_element(rule_def, "active_hours");
char* active_weekdays = get_map_element(rule_def, "active_weekdays");
@ -174,7 +169,7 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
dcat_and_free(&single_check, &tmp, 1, 1);
}
else if(active_hours != NULL && active_weekdays != NULL)
{
{
char* tmp = dynamic_strcat(5, " -m timerange --hours \"", active_hours, "\" --weekdays \"", active_weekdays, "\" " );
dcat_and_free(&single_check, &tmp, 1, 1);
}
@ -189,7 +184,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
dcat_and_free(&single_check, &tmp, 1, 1);
}
/*
* layer7 && ipp2p can not be negated. To negate them
* set a mark/connmark and negate that
@ -216,8 +210,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
dcat_and_free(&single_check, &tmp, 1, 1);
}
/* make sure proto is lower case */
char* proto = get_map_element(rule_def, "proto");
if(proto == NULL)
@ -236,19 +228,15 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
}
int include_proto = strcmp(proto, "both") == 0 ? 0 : 1;
/* parse multi rules */
int mask_byte_index = 0;
list* initial_mask_list = initialize_list();
list* final_mask_list = initialize_list();
/* url matches are a bit of a special case, handle them first */
/* we have to save this mask_byte_index specially, because it must be set separately, so it only gets set if packet is http request */
int url_mask_byte_index = mask_byte_index;
char* url_match_vars[] = { "url_contains", "url_regex", "url_exact", "url_domain_contains", "url_domain_regex", "url_domain_exact" };
char* url_neg_match_vars[] = { "not_url_contains", "not_url_regex", "not_url_exact", "not_url_domain_contains", "not_url_domain_regex", "not_url_domain_exact" };
char* url_prefixes1[] = { " -m weburl ", " -m weburl ", " -m weburl ", " -m weburl --domain_only ", " -m weburl --domain_only ", " -m weburl --domain_only " };
@ -257,7 +245,7 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
int url_var_index=0;
int url_rule_count=0;
int url_is_negated=0;
for(url_is_negated=0; url_is_negated < 2 && url_rule_count == 0; url_is_negated++)
{
char** url_vars = url_is_negated ? url_neg_match_vars : url_match_vars;
@ -272,7 +260,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
}
}
url_is_negated--;
proto = url_rule_count > 0 ? "tcp" : proto;
int url_is_multi = url_rule_count <= 1 ? 0 : 1;
@ -294,7 +281,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
push_list(final_mask_list, (void*)&url_is_multi);
mask_byte_index++;
/* mark matches */
char** mark_def = get_map_element(rule_def, "mark");
int mark_is_negated = mark_def == NULL ? 1 : 0;
@ -304,7 +290,7 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
int mark_is_multi = compute_multi_rules(mark_def, multi_rules, &single_check, mark_is_negated, rule_prefix, " -m mark ", " --mark ", mark_is_negated, 0, mask_byte_index, proto, include_proto, 0) == 2;
push_list(initial_mask_list, (void*)&mark_is_negated);
push_list(final_mask_list, (void*)&mark_is_multi);
mask_byte_index++;
mask_byte_index++;
/* connmark matches */
char** connmark_def = get_map_element(rule_def, "connmark");
@ -314,11 +300,10 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
int connmark_is_multi = compute_multi_rules(connmark_def, multi_rules, &single_check, 0, rule_prefix, " -m connmark ", " --mark ", connmark_is_negated, 0, mask_byte_index, proto, include_proto, 0) == 2;
push_list(initial_mask_list, (void*)&connmark_is_negated);
push_list(final_mask_list, (void*)&connmark_is_multi);
mask_byte_index++;
mask_byte_index++;
/*
* for ingress source = remote, destination = local
* for ingress source = remote, destination = local
* for egress source = local, destination = remote
*
* addresses are a bit tricky, since we need to handle 3 different kinds of matches: ips, ip ranges and macs
@ -371,15 +356,13 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
}
}
}
push_list(initial_mask_list, (void*)(addr_negated + addr_index));
push_list(final_mask_list, (void*)(is_multi == 1 ? &is_true : &is_false) );
mask_byte_index++;
}
}
char** sport_def = get_map_element(rule_def, (is_ingress ? "remote_port" : "local_port"));
int sport_is_negated = sport_def == NULL ? 1 : 0;
sport_def = sport_def == NULL ? get_map_element(rule_def, (is_ingress ? "not_remote_port" : "not_local_port")) : sport_def;
@ -389,7 +372,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
push_list(final_mask_list, (void*)&sport_is_multi);
mask_byte_index++;
char** dport_def = get_map_element(rule_def, (is_ingress ? "local_port" : "remote_port"));
int dport_is_negated = dport_def == NULL ? 1 : 0;
dport_def = dport_def == NULL ? get_map_element(rule_def, (is_ingress ? "not_local_port" : "not_remote_port")) : dport_def;
@ -401,8 +383,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
list* all_rules = initialize_list();
//if no target_options specified, make sure it's an empty string, not null
target_options = (target_options == NULL) ? "" : target_options;
//if target_options is empty and we're rejecting and proto is tcp, set options to --reject-with tcp-reset instead of default
@ -416,7 +396,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
compute_multi_rules(dummy_multi, multi_rules, &single_check, 1, rule_prefix, " ", "", 0, 0, mask_byte_index, proto, requires_proto, 0);
mask_byte_index++;
}
/*
printf("final mask length = %ld\n", final_mask_list->length);
@ -445,7 +424,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
{
*next_is_multi = 1;
}
unsigned long next_mark_bit = 0x01000000 * (unsigned long)pow(2, next_mask_index) * (*next_is_multi);
final_match = final_match + next_mark_bit;
@ -461,7 +439,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
/* else it's last single_check mark which is never initialized to one */
}
if(initial_main_mark > 0)
{
//set main_mark unconditionally
@ -476,7 +453,7 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
sprintf(mark, "0x%lX", initial_url_mark);
push_list(all_rules, dynamic_strcat(5, rule_prefix, " -p tcp -m weburl --contains http -j CONNMARK --set-mark ", mark, "/", mark));
}
//put all rules in place from multi_rules list
while(multi_rules->length > 0)
{
@ -488,7 +465,7 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
//if final mark matches perfectly with mask of 0xFF000000, jump to (REJECT/ACCEPT) target
char final_match_str[12];
sprintf(final_match_str, "0x%lX", final_match);
//if we're rejecting, no target options are specified, and no proto is specified add two rules: one for tcp with tcp-reject, and one for everything else
if(safe_strcmp(target, "REJECT") == 0 && safe_strcmp(target_options, "") == 0 && safe_strcmp(proto, "both"))
{
@ -507,7 +484,7 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
else
{
if( strcmp(proto, "both") == 0 )
{
{
if( dport_def == NULL && sport_def == NULL )
{
if(safe_strcmp(target, "REJECT") == 0 && safe_strcmp(target_options, "") == 0 )
@ -556,7 +533,6 @@ char** compute_rules(string_map *rule_def, char* table, char* chain, int is_ingr
return block_rule_list;
}
/* returns 0 if no rules found, 1 if one rule found AND included in single_check, otherwise 2 */
int compute_multi_rules(char** def, list* multi_rules, char** single_check, int never_single, char* rule_prefix, char* test_prefix1, char* test_prefix2, int is_negation1, int is_negation2, int mask_byte_index, char* proto, int requires_proto, int quoted_args)
{
@ -568,7 +544,7 @@ int compute_multi_rules(char** def, list* multi_rules, char** single_check, int
}
if(def != NULL)
{
int num_rules;
int num_rules;
for(num_rules=0; def[num_rules] != NULL; num_rules++){}
if(num_rules == 1 && !never_single)
{
@ -584,7 +560,6 @@ int compute_multi_rules(char** def, list* multi_rules, char** single_check, int
sprintf(mask_str, "0x%lX", mask);
char* connmark_part = dynamic_strcat(4, " -j CONNMARK --set-mark ", (is_negation ? "0x0" : mask_str), "/", mask_str);
int rule_index =0;
for(rule_index=0; def[rule_index] != NULL; rule_index++)
{
@ -613,12 +588,6 @@ int compute_multi_rules(char** def, list* multi_rules, char** single_check, int
return parse_type;
}
string_map* get_rule_definition(char* package, char* section)
{
string_map* definition = NULL;
@ -637,8 +606,8 @@ string_map* get_rule_definition(char* package, char* section)
{
struct uci_element *e;
definition = initialize_string_map(1);
uci_foreach_element(&s->options, e)
uci_foreach_element(&s->options, e)
{
char* option_name = strdup(e->name);
to_lowercase(option_name);
@ -651,7 +620,7 @@ string_map* get_rule_definition(char* package, char* section)
}
}
uci_free_context(ctx);
return definition;
}
@ -661,15 +630,15 @@ int parse_option(char* option_name, char* option_value, string_map* definition)
if( safe_strcmp(option_name, "proto") == 0 ||
safe_strcmp(option_name, "layer7") == 0 ||
safe_strcmp(option_name, "ipp2p") == 0 ||
safe_strcmp(option_name, "max_pkt_size") == 0 ||
safe_strcmp(option_name, "min_pkt_size") ==0
safe_strcmp(option_name, "max_pkt_size") == 0 ||
safe_strcmp(option_name, "min_pkt_size") ==0
)
{
valid_option = 1;
set_map_element(definition, option_name, strdup(option_value));
}
else if( safe_strcmp(option_name, "active_hours") == 0 ||
safe_strcmp(option_name, "active_weekly_ranges") == 0 ||
else if( safe_strcmp(option_name, "active_hours") == 0 ||
safe_strcmp(option_name, "active_weekly_ranges") == 0 ||
safe_strcmp(option_name, "active_weekdays") == 0
)
{
@ -692,7 +661,7 @@ int parse_option(char* option_name, char* option_value, string_map* definition)
else if( safe_strcmp(option_name, "remote_addr") == 0 ||
safe_strcmp(option_name, "local_addr") == 0 ||
safe_strcmp(option_name, "not_remote_addr") == 0 ||
safe_strcmp(option_name, "not_local_addr") == 0
safe_strcmp(option_name, "not_local_addr") == 0
)
{
char*** parsed_addr = parse_ips_and_macs(option_value);
@ -709,7 +678,7 @@ int parse_option(char* option_name, char* option_value, string_map* definition)
else if( safe_strcmp(option_name, "remote_port") == 0 ||
safe_strcmp(option_name, "local_port") == 0 ||
safe_strcmp(option_name, "not_remote_port") == 0 ||
safe_strcmp(option_name, "not_local_port") == 0
safe_strcmp(option_name, "not_local_port") == 0
)
{
char** parsed_ports = parse_ports(option_value);
@ -730,13 +699,13 @@ int parse_option(char* option_name, char* option_value, string_map* definition)
truncate_if_starts_with(option_name, "not_url_exact") ||
truncate_if_starts_with(option_name, "not_url_domain_contains") ||
truncate_if_starts_with(option_name, "not_url_domain_regex") ||
truncate_if_starts_with(option_name, "not_url_domain_exact")
truncate_if_starts_with(option_name, "not_url_domain_exact")
)
{
/*
* may be a quoted list of urls to block, so attempt to parse this
* if no quotes found, match on unquoted expresssion
* we don't need to de-escape quotes because when we define rule,
* we don't need to de-escape quotes because when we define rule,
* we call iptables from system, and through the shell, which will de-escape quotes for us
*/
list* parsed_quoted = parse_quoted_list(option_value, '\"', '\\', 0);
@ -759,7 +728,6 @@ int parse_option(char* option_name, char* option_value, string_map* definition)
return valid_option;
}
// this function dynamically allocates memory for
// the option string, but since this program exits
// almost immediately (after printing variable info)
@ -796,9 +764,6 @@ char* get_option_value_string(struct uci_option* uopt)
return opt_str;
}
char*** parse_ips_and_macs(char* addr_str)
{
unsigned long num_pieces;
@ -806,7 +771,7 @@ char*** parse_ips_and_macs(char* addr_str)
list* ip_list = initialize_list();
list* ip_range_list = initialize_list();
list* mac_list = initialize_list();
int ip_part_index;
for(ip_part_index=0; addr_parts[ip_part_index] != NULL; ip_part_index++)
{
@ -828,7 +793,7 @@ char*** parse_ips_and_macs(char* addr_str)
int end_ip[4];
int start_valid = sscanf(start, "%d.%d.%d.%d", start_ip, start_ip+1, start_ip+2, start_ip+3);
int end_valid = sscanf(end, "%d.%d.%d.%d", end_ip, end_ip+1, end_ip+2, end_ip+3);
if(start_valid == 4 && end_valid == 4)
{
//get_ip_range_strs(start_ip, end_ip, "", 4, ip_list);
@ -836,7 +801,7 @@ char*** parse_ips_and_macs(char* addr_str)
}
free(start);
free(end);
free(end);
free(range_parts);
//free(next_str);
}
@ -851,7 +816,7 @@ char*** parse_ips_and_macs(char* addr_str)
}
}
free(addr_parts);
unsigned long num1, num2, num3;
char*** return_value = (char***)malloc(3*sizeof(char**));
return_value[MATCH_IP_INDEX] = (char**)destroy_list(ip_list, DESTROY_MODE_RETURN_VALUES, &num1);
@ -869,8 +834,6 @@ char*** parse_ips_and_macs(char* addr_str)
return return_value;
}
char** parse_ports(char* port_str)
{
unsigned long num_pieces;
@ -888,7 +851,6 @@ char** parse_ports(char* port_str)
return ports;
}
/*
* parses a list of marks/connmarks
* the max_mask parameter specfies a maximal mask that will be used
@ -896,8 +858,8 @@ char** parse_ports(char* port_str)
* (by defining [mark]/[mask]) this is bitwise-anded with the maximum
* mask to get the final mask. This is especially necessary for
* connmarks, because the mechanism to handle negation when multiple
* test rules are needed uses the last (high) byte of the connmark
* address space, so this HAS to be masked out when matching
* test rules are needed uses the last (high) byte of the connmark
* address space, so this HAS to be masked out when matching
* connmarks, using max_mask=0x00FFFFFF
*/
char** parse_marks(char* list_str, unsigned long max_mask)
@ -912,7 +874,7 @@ char** parse_marks(char* list_str, unsigned long max_mask)
free(marks);
marks = NULL;
}
else
else
{
int mark_index;
for(mark_index = 0; marks[mark_index] != NULL; mark_index++)
@ -928,9 +890,9 @@ char** parse_marks(char* list_str, unsigned long max_mask)
unsigned long mask = 0xFFFFFFFF;
mask_start++;
sscanf(mask_start, "%lX", &mask);
mask = mask & max_mask;
*(mask_start) = '\0';
char new_mask_str[12];
sprintf(new_mask_str, "0x%lX", mask);
@ -950,14 +912,13 @@ char** parse_marks(char* list_str, unsigned long max_mask)
return marks;
}
/*
* parses list of quoted strings, ignoring escaped quote characters that are not themselves escaped
/*
* parses list of quoted strings, ignoring escaped quote characters that are not themselves escaped
* Note that we don't de-escape anything here. If necessary that should be done elsewhere.
*/
*/
list* parse_quoted_list(char* list_str, char quote_char, char escape_char, char add_remainder_if_uneven_quotes)
{
long num_quotes = 0;
long list_index = 0;
char previous_is_quoted = 0;
@ -966,11 +927,11 @@ list* parse_quoted_list(char* list_str, char quote_char, char escape_char, char
num_quotes = num_quotes + ( list_str[list_index] == quote_char && !previous_is_quoted ? 1 : 0);
previous_is_quoted = list_str[list_index] == escape_char && !previous_is_quoted ? 1 : 0;
}
char** pieces = (char**)malloc( ((long)(num_quotes/2)+2) * sizeof(char*) );
long piece_index = 0;
long next_start_index=-1;
previous_is_quoted = 0;
previous_is_quoted = 0;
for(list_index=0; list_str[list_index] != '\0'; list_index++)
{
if( list_str[list_index] == quote_char && !previous_is_quoted )
@ -1018,11 +979,10 @@ list* parse_quoted_list(char* list_str, char quote_char, char escape_char, char
push_list(quoted_list, strdup(list_str));
}
free(pieces);//but do free array of char* pointers, we don't need it anymore
return quoted_list;
}
int truncate_if_starts_with(char* test_str, char* prefix)
{
int prefix_length = strlen(prefix);

View File

@ -18,7 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -27,6 +26,7 @@
#include <erics_tools.h>
#include <uci.h>
#include <ipt_bwctl.h>
#define malloc safe_malloc
#define strdup safe_strdup
@ -35,7 +35,6 @@ void backup_quota(char* quota_id, char* quota_backup_dir);
char* get_uci_option(struct uci_context* ctx,char* package_name, char* section_name, char* option_name);
char* get_option_value_string(struct uci_option* uopt);
int main(void)
{
struct uci_context *ctx = uci_alloc_context();
@ -44,18 +43,17 @@ int main(void)
/* for each ip have uint64_t[6], */
string_map *id_ip_to_bandwidth = initialize_string_map(1);
string_map *id_ip_to_percents = initialize_string_map(1);
string_map *id_ip_to_percents = initialize_string_map(1);
string_map *id_ip_to_limits = initialize_string_map(1);
list *id_to_time = initialize_list();
while(quota_sections->length > 0)
{
char* next_quota = shift_list(quota_sections);
/* base id for quota is the ip associated with it*/
char *id = get_uci_option(ctx, "firewall", next_quota, "id");
char* ip = get_uci_option(ctx, "firewall", next_quota, "ip");
char* ip = get_uci_option(ctx, "firewall", next_quota, "ip");
if(ip == NULL)
{
ip = strdup("ALL");
@ -75,10 +73,6 @@ int main(void)
id = strdup(ip);
}
string_map* ip_to_bandwidth = get_string_map_element(id_ip_to_bandwidth, id);
ip_to_bandwidth = ip_to_bandwidth == NULL ? initialize_string_map(1) : ip_to_bandwidth;
set_string_map_element(id_ip_to_bandwidth, id, ip_to_bandwidth);
@ -104,7 +98,7 @@ int main(void)
char* weekdays_var = is_off_peak ? offpeak_weekdays : onpeak_weekdays;
char* weekly_ranges_var = is_off_peak ? offpeak_weekly_ranges : onpeak_weekly_ranges;
char* active_var = is_off_peak ? strdup("except") : strdup("only");
if(weekly_ranges_var != NULL)
{
if(hours_var != NULL) { free(hours_var); hours_var=NULL; }
@ -114,7 +108,7 @@ int main(void)
weekdays_var = weekdays_var == NULL ? strdup("") : weekdays_var;
weekly_ranges_var = weekly_ranges_var == NULL ? strdup("") : weekly_ranges_var;
push_list(id_to_time, dynamic_strcat(11, "quotaTimes[\"", id, "\"] = [\"", hours_var, "\", \"", weekdays_var, "\", \"", weekly_ranges_var ,"\", \"", active_var, "\"];"));
free(hours_var);
free(weekdays_var);
free(weekly_ranges_var);
@ -127,8 +121,7 @@ int main(void)
char* types[] = { "combined_limit", "ingress_limit", "egress_limit" };
char* postfixes[] = { "_combined", "_ingress", "_egress" };
int type_index;
for(type_index=0; type_index < 3; type_index++)
{
@ -156,8 +149,7 @@ int main(void)
addr.s_addr = next.ip;
next_ip = strdup(inet_ntoa(addr));
}
uint64_t *bw_list = get_string_map_element(ip_to_bandwidth,next_ip);
if(bw_list == NULL)
{
@ -172,7 +164,7 @@ int main(void)
}
bw_list[type_index] = 1;
bw_list[type_index+3] = next.bw;
char bw_str[50];
sprintf(bw_str, "%lld", next.bw);
double bw_percent;
@ -190,7 +182,7 @@ int main(void)
{
bw_percent = 100.0;
}
double* percent_list = get_string_map_element(ip_to_percents, next_ip);
if(percent_list == NULL)
{
@ -216,14 +208,12 @@ int main(void)
}
free(type_id);
free(limit);
}
}
free(id);
free(ip);
free(next_quota);
}
unsigned long num_ids;
char** id_list = (char**)get_string_map_keys(id_ip_to_bandwidth, &num_ids);
@ -255,7 +245,7 @@ int main(void)
}
printf("];\n");
}
}
}
printf("var quotaTimes = new Array();\n");
printf("var quotaUsed = new Array();\n");
@ -275,12 +265,11 @@ int main(void)
string_map* ip_to_bandwidth = get_string_map_element(id_ip_to_bandwidth, next_id);
string_map* ip_to_percents = get_string_map_element(id_ip_to_percents, next_id);
string_map* ip_to_limits = get_string_map_element(id_ip_to_limits, next_id);
printf("quotaUsed[ \"%s\" ] = [];\n", next_id);
printf("quotaPercents[ \"%s\" ] = [];\n", next_id);
printf("quotaLimits[ \"%s\" ] = [];\n", next_id);
if(ip_to_bandwidth != NULL)
{
unsigned long num_ips;
@ -334,7 +323,6 @@ int main(void)
}
}
unsigned long num;
destroy_list(quota_sections, DESTROY_MODE_FREE_VALUES, &num);
uci_free_context(ctx);
@ -344,7 +332,6 @@ int main(void)
list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* section_type)
{
struct uci_package *p = NULL;
struct uci_element *e = NULL;
@ -363,7 +350,6 @@ list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* sec
return sections_of_type;
}
char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_name, char* option_name)
{
char* option_value = NULL;
@ -387,9 +373,6 @@ char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_
return option_value;
}
// this function dynamically allocates memory for
// the option string, but since this program exits
// almost immediately (after printing variable info)
@ -425,5 +408,3 @@ char* get_option_value_string(struct uci_option* uopt)
return opt_str;
}

View File

@ -1,4 +1,4 @@
/* restore_quotas -- Used to initialize and restore bandwidth quotas based on UCI config files
/* restore_quotas -- Used to initialize and restore bandwidth quotas based on UCI config files
* and any previously saved quota data in /usr/data/quotas
* Originally designed for use with Gargoyle router firmware (gargoyle-router.com)
*
@ -25,7 +25,6 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@ -33,6 +32,7 @@
#include <erics_tools.h>
#include <uci.h>
#include <ipt_bwctl.h>
#define malloc safe_malloc
#define strdup safe_strdup
@ -40,8 +40,6 @@
#define EGRESS_INDEX 1
#define COMBINED_INDEX 2
void restore_backup_for_id(char* id, char* quota_backup_dir, unsigned char is_individual_other, list* defined_ip_groups);
uint32_t ip_to_host_int(char* ip_str);
uint32_t* ip_range_to_host_ints(char* ip_str);
@ -64,7 +62,7 @@ int main(int argc, char** argv)
char* death_mask = NULL;
char* crontab_line = NULL;
int ret;
unsigned char full_qos_active = 0;
char c;
@ -131,8 +129,6 @@ int main(int argc, char** argv)
return 0;
}
struct uci_context *ctx = uci_alloc_context();
struct uci_ptr ptr;
@ -153,7 +149,6 @@ int main(int argc, char** argv)
char* base_id = get_uci_option(ctx, "firewall", next_quota, "id");
char* exceeded_up_speed_str = get_uci_option(ctx, "firewall", next_quota, "exceeded_up_speed");
char* exceeded_down_speed_str = get_uci_option(ctx, "firewall", next_quota, "exceeded_down_speed");
if(base_id != NULL)
{
@ -175,7 +170,7 @@ int main(int argc, char** argv)
if(oldval != NULL) { free(oldval); }
oldval = set_long_map_element(down_speeds, down, strdup(exceeded_down_speed_str) );
if(oldval != NULL) { free(oldval); }
}
}
}
@ -183,16 +178,16 @@ int main(int argc, char** argv)
free(exceeded_up_speed_str);
free(exceeded_down_speed_str);
}
unsigned long num_destroyed;
destroy_list(quota_sections, DESTROY_MODE_FREE_VALUES, &num_destroyed);
quota_sections = quota_section_buf;
/* initialize qos mark maps */
unsigned long mark_band = 2;
int upload_shift = 0;
int download_shift = 8;
while(up_speeds->num_elements > 0)
{
unsigned long mark = mark_band << upload_shift;
@ -204,6 +199,7 @@ int main(int argc, char** argv)
free(next_up_speed);
mark_band++;
}
mark_band = 2;
while(down_speeds->num_elements > 0)
{
@ -217,15 +213,12 @@ int main(int argc, char** argv)
mark_band++;
}
/* initialize chains */
run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N forward_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N egress_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N ingress_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -N combined_quotas 2>/dev/null"), 1);
run_shell_command("iptables -t nat -N quota_redirects 2>/dev/null", 0);
run_shell_command("iptables -t nat -A quota_redirects -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null", 0);
run_shell_command("iptables -t nat -I zone_lan_prerouting -j quota_redirects 2>/dev/null", 0);
@ -235,7 +228,6 @@ int main(int argc, char** argv)
run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I INPUT 2 -i ", wan_if, no_death_mark_test, " -j combined_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I OUTPUT 1 -o ", wan_if, no_death_mark_test, " -j egress_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -I OUTPUT 2 -o ", wan_if, no_death_mark_test, " -j combined_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(3, "iptables -t ", quota_table, " -I FORWARD -j forward_quotas 2>/dev/null"), 1);
run_shell_command(dynamic_strcat(6, "iptables -t ", quota_table, " -A forward_quotas -o ", wan_if, no_death_mark_test, " -j egress_quotas 2>/dev/null"), 1);
@ -283,7 +275,7 @@ int main(int argc, char** argv)
}
}
free(quota_enabled_var);
if(enabled)
{
char* ip = get_uci_option(ctx, "firewall", next_quota, "ip");
@ -314,8 +306,7 @@ int main(int argc, char** argv)
ip = dynamic_replace(ip, "- ", "-");
free(tmp_ip);
}
if( (strcmp(ip, "ALL_OTHERS_COMBINED") == 0 || strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0) && (!process_other_quota) )
{
push_list(other_quota_section_names, strdup(next_quota));
@ -328,7 +319,7 @@ int main(int argc, char** argv)
/* this is an explicitly defined ip or ip range, so save it for later, to deal with individual other overlap problem */
push_list(defined_ip_groups, strdup(ip));
}
/* compute proper base id for rule, adding variable to uci if necessary */
char* quota_base_id = get_uci_option(ctx, "firewall", next_quota, "id");
if(quota_base_id == NULL)
@ -338,7 +329,7 @@ int main(int argc, char** argv)
char** split_ip = split_on_separators(ip, id_breaks, 3, -1, 0, &num_pieces);
char* first_ip = dynamic_replace(split_ip[0], "/", "_");
free_null_terminated_string_array(split_ip);
quota_base_id = strdup(first_ip);
unsigned long next_postfix_count = 0;
while( get_string_map_element(defined_base_ids, quota_base_id) != NULL)
@ -346,7 +337,7 @@ int main(int argc, char** argv)
char next_postfix[20];
if(next_postfix_count > 25)
{
sprintf(next_postfix, "_%c", ('A' + next_postfix_count));
sprintf(next_postfix, "_%ld", ('A' + next_postfix_count));
}
else
{
@ -359,7 +350,7 @@ int main(int argc, char** argv)
/* D for dummy place holder */
set_string_map_element(defined_base_ids, quota_base_id, strdup("D"));
/* add id we've decided on to UCI */
char* var_set = dynamic_strcat(4, "firewall.", next_quota, ".id=", quota_base_id);
if (uci_lookup_ptr(ctx, &ptr, var_set, true) == UCI_OK)
@ -375,7 +366,7 @@ int main(int argc, char** argv)
do_restore = strcmp(ignore_backup, "1") == 0 ? 0 : 1;
if(!do_restore)
{
//remove variable from uci
//remove variable from uci
char* var_name = dynamic_strcat(3, "firewall.", next_quota, ".ignore_backup_at_next_restore");
if (uci_lookup_ptr(ctx, &ptr, var_name, true) == UCI_OK)
{
@ -385,15 +376,13 @@ int main(int argc, char** argv)
}
}
free(ignore_backup);
char* reset_interval = get_uci_option(ctx, "firewall", next_quota, "reset_interval");
char* reset = strdup("");
if(reset_interval != NULL)
{
char* reset_time = get_uci_option(ctx, "firewall", next_quota, "reset_time");
char* interval_option = strdup(" --reset_interval ");
reset = dcat_and_free(&reset, &interval_option, 1, 1);
reset = dcat_and_free(&reset, &reset_interval, 1, 1);
@ -404,9 +393,9 @@ int main(int argc, char** argv)
reset = dcat_and_free(&reset, &reset_time, 1, 1);
}
}
char* time_match_str = strdup("");
char* time_match_str = strdup("");
char* offpeak_hours = get_uci_option(ctx, "firewall", next_quota, "offpeak_hours");
char* offpeak_weekdays = get_uci_option(ctx, "firewall", next_quota, "offpeak_weekdays");
char* offpeak_weekly_ranges = get_uci_option(ctx, "firewall", next_quota, "offpeak_weekly_ranges");
@ -415,7 +404,6 @@ int main(int argc, char** argv)
char* onpeak_weekdays = get_uci_option(ctx, "firewall", next_quota, "onpeak_weekdays");
char* onpeak_weekly_ranges = get_uci_option(ctx, "firewall", next_quota, "onpeak_weekly_ranges");
if(offpeak_hours != NULL || offpeak_weekdays != NULL || offpeak_weekly_ranges != NULL || onpeak_hours != NULL || onpeak_weekdays != NULL || onpeak_weekly_ranges != NULL)
{
unsigned char is_off_peak = (offpeak_hours != NULL || offpeak_weekdays != NULL || offpeak_weekly_ranges != NULL) ? 1 : 0;
@ -432,15 +420,15 @@ int main(int argc, char** argv)
time_match_str = dcat_and_free(&time_match_str, &timerange_match, 1,1);
if(hours_var != NULL && weekly_ranges_var == NULL)
{
time_match_str = dcat_and_free(&time_match_str, &hour_match, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &hours_var, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &quote_end, 1, 0);
time_match_str = dcat_and_free(&time_match_str, &hour_match, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &hours_var, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &quote_end, 1, 0);
}
if(weekdays_var != NULL && weekly_ranges_var == NULL)
{
time_match_str = dcat_and_free(&time_match_str, &weekday_match, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &weekday_match, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &weekdays_var, 1, 1);
time_match_str = dcat_and_free(&time_match_str, &quote_end, 1, 0);
time_match_str = dcat_and_free(&time_match_str, &quote_end, 1, 0);
}
if(weekly_ranges_var != NULL)
{
@ -450,11 +438,11 @@ int main(int argc, char** argv)
}
free(quote_end);
}
char* types[] = { "ingress_limit", "egress_limit", "combined_limit" };
char* postfixes[] = { "_ingress", "_egress", "_combined" };
char* chains[] = { "ingress_quotas", "egress_quotas", "combined_quotas" };
int type_index;
for(type_index=0; type_index < 3; type_index++)
{
@ -463,28 +451,28 @@ int main(int argc, char** argv)
char* subnet_definition = strdup("");
char* limit = get_uci_option(ctx, "firewall", next_quota, types[type_index]);
char* type_id = dynamic_strcat(2, quota_base_id, postfixes[type_index] );
char* up_qos_mark = get_string_map_element(upload_qos_marks, exceeded_up_speed_str);
char* down_qos_mark = get_string_map_element(download_qos_marks, exceeded_down_speed_str);
if(full_qos_active)
{
up_qos_mark = get_uci_option(ctx, "firewall", next_quota, "exceeded_up_class_mark");
down_qos_mark = get_uci_option(ctx, "firewall", next_quota, "exceeded_down_class_mark");
}
}
/*
/*
* need to do ip test even if limit is null, because ALL_OTHERS quotas should not apply when any of the three types of explicit limit is defined
* and we therefore need to use this test to set mark indicating an explicit quota has been checked
*/
char* ip_test = strdup("");
char* ip_test = strdup("");
if( strcmp(ip, "ALL_OTHERS_COMBINED") != 0 && strcmp(ip, "ALL_OTHERS_INDIVIDUAL") != 0 && strcmp(ip, "ALL") != 0 )
{
char* src_test = strstr(ip, "-") == NULL ? dynamic_strcat(3, " --src ", ip, " ") : dynamic_strcat(3, " -m iprange --src-range ", ip, " ");
char* dst_test = strstr(ip, "-") == NULL ? dynamic_strcat(3, " --dst ", ip, " ") : dynamic_strcat(3, " -m iprange --dst-range ", ip, " ");
if(strstr(ip, ",") != NULL || strstr(ip, " ") != NULL || strstr(ip, "\t") != NULL )
{
char ip_breaks[] = { ',', ' ', '\t' };
@ -560,14 +548,12 @@ int main(int argc, char** argv)
{
applies_to = strdup("individual_local");
}
char *subnet_option = strdup(" --subnet ");
subnet_definition = dcat_and_free(&subnet_definition, &subnet_option, 1, 1);
subnet_definition = dcat_and_free(&subnet_definition, &local_subnet, 1, 0);
}
}
if(up_qos_mark != NULL && down_qos_mark != NULL)
{
@ -582,11 +568,11 @@ int main(int argc, char** argv)
char* other_type_id = dynamic_strcat(2, quota_base_id, postfixes[other_type_index] );
if(type_index == EGRESS_INDEX)
{
run_shell_command(dynamic_strcat(10, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", other_type_id, "\" --bcheck_with_src_dst_swap ", set_egress_mark), 1);
run_shell_command(dynamic_strcat(10, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", other_type_id, "\" --bcheck_with_src_dst_swap ", set_egress_mark), 1);
}
else
{
run_shell_command(dynamic_strcat(10, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", other_type_id, "\" --bcheck_with_src_dst_swap ", set_ingress_mark), 1);
run_shell_command(dynamic_strcat(10, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", other_type_id, "\" --bcheck_with_src_dst_swap ", set_ingress_mark), 1);
}
free(other_type_id);
}
@ -595,13 +581,13 @@ int main(int argc, char** argv)
free(set_egress_mark);
free(set_ingress_mark);
}
if(limit != NULL)
{
if(up_qos_mark != NULL && down_qos_mark != NULL)
{
char* set_egress_mark = dynamic_strcat(2, " -j MARK --set-mark ", up_qos_mark);
char* set_ingress_mark = dynamic_strcat(2, " -j MARK --set-mark ", down_qos_mark);
char* set_ingress_mark = dynamic_strcat(2, " -j MARK --set-mark ", down_qos_mark);
if(strcmp(types[type_index], "egress_limit") == 0)
{
run_shell_command(dynamic_strcat(15, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --type ", applies_to, subnet_definition, " --greater_than ", limit, reset, set_egress_mark), 1);
@ -624,7 +610,6 @@ int main(int argc, char** argv)
//insert quota block rule
run_shell_command(dynamic_strcat(15, "iptables -t ", quota_table, " -A ", chains[type_index], ip_test, time_match_str, " -m bandwidth --id \"", type_id, "\" --type ", applies_to, subnet_definition, " --greater_than ", limit, reset, set_death_mark), 1);
//insert redirect rule
if(strcmp(ip, "ALL") == 0 || strcmp(ip, "ALL_OTHERS_INDIVIDUAL") == 0)
{
@ -656,7 +641,6 @@ int main(int argc, char** argv)
}
}
//restore from backup
if(do_restore)
{
@ -670,7 +654,6 @@ int main(int argc, char** argv)
run_shell_command(dynamic_strcat(5, "iptables -t ", quota_table, " -A ", chains[type_index], " -j CONNMARK --set-mark 0x0/0x0F000000 2>/dev/null"), 1);
}
free(ip_test);
free(applies_to);
free(subnet_definition);
@ -693,7 +676,6 @@ int main(int argc, char** argv)
free(exceeded_down_speed_str);
}
free(next_quota);
}
run_shell_command("iptables -t nat -A quota_redirects -j CONNMARK --set-mark 0x0/0xFF000000 2>/dev/null", 0);
@ -804,17 +786,16 @@ void restore_backup_for_id(char* id, char* quota_backup_dir, unsigned char is_in
ip_bw* ptr = loaded_backup_data + ip_index;
push_list(ip_bw_list, ptr);
}
unsigned long num_groups = 0;
char** group_strs = (char**)get_list_values(defined_ip_groups, &num_groups);
unsigned long group_index;
for(group_index = 0; group_index < num_groups; group_index++)
{
filter_group_from_list(&ip_bw_list, group_strs[group_index]);
}
//rebuild the backup data array from the filtered list
if(num_ips != ip_bw_list->length)
{
@ -828,7 +809,7 @@ void restore_backup_for_id(char* id, char* quota_backup_dir, unsigned char is_in
free(loaded_backup_data);
loaded_backup_data = adj_backup;
}
destroy_list(ip_bw_list, DESTROY_MODE_IGNORE_VALUES, &num_groups);
free(group_strs); //don't want to destroy values, they're still contained in list, so just destroy container array
}
@ -871,7 +852,7 @@ list* filter_group_from_list(list** orig_ip_bw_list, char* ip_group_str)
unsigned long num_groups = 0;
char** split_group = split_on_separators(dyn_group_str, group_breaks, 3, -1, 0, &num_groups);
unsigned long group_index;
for(group_index = 0; group_index < num_groups; group_index++)
{
uint32_t* range = ip_range_to_host_ints( split_group[group_index] );
@ -894,6 +875,7 @@ list* filter_group_from_list(list** orig_ip_bw_list, char* ip_group_str)
destroy_list(*orig_ip_bw_list, DESTROY_MODE_IGNORE_VALUES, &num_destroyed);
*orig_ip_bw_list = new_ip_bw_list;
}
free_null_terminated_string_array(split_group);
free(dyn_group_str);
@ -906,8 +888,7 @@ uint32_t* ip_range_to_host_ints(char* ip_str)
uint32_t* ret_val = (uint32_t*)malloc(2*sizeof(uint32_t));
uint32_t start = 0;
uint32_t end = 0;
unsigned long num_pieces = 0;
char ip_breaks[] = "/-";
char** split_ip = split_on_separators(ip_str, ip_breaks, 2, -1, 0, &num_pieces);
@ -943,7 +924,6 @@ uint32_t* ip_range_to_host_ints(char* ip_str)
return ret_val;
}
uint32_t ip_to_host_int(char* ip_str)
{
struct in_addr inp;
@ -951,19 +931,17 @@ uint32_t ip_to_host_int(char* ip_str)
return (uint32_t)ntohl(inp.s_addr);
}
void delete_chain_from_table(char* table, char* delete_chain)
{
char *command = dynamic_strcat(3, "iptables -t ", table, " -L -n --line-numbers 2>/dev/null");
unsigned long num_lines = 0;
char** table_dump = get_shell_command_output_lines(command, &num_lines );
free(command);
free(command);
unsigned long line_index;
char* current_chain = NULL;
list* delete_commands = initialize_list();
for(line_index=0; line_index < num_lines; line_index++)
{
char* line = table_dump[line_index];
@ -975,7 +953,7 @@ void delete_chain_from_table(char* table, char* delete_chain)
if(current_chain != NULL) { free(current_chain); }
current_chain = strdup(line_pieces[1]);
}
else
else
{
unsigned long line_num;
int read = sscanf(line_pieces[0], "%ld", &line_num);
@ -994,7 +972,7 @@ void delete_chain_from_table(char* table, char* delete_chain)
free_null_terminated_string_array(line_pieces);
}
free_null_terminated_string_array(table_dump);
/* final two commands to flush chain being deleted and whack it */
unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -F ", delete_chain, " 2>/dev/null"));
unshift_list(delete_commands, dynamic_strcat(5, "iptables -t ", table, " -X ", delete_chain, " 2>/dev/null"));
@ -1005,7 +983,6 @@ void delete_chain_from_table(char* table, char* delete_chain)
char *next_command = (char*)pop_list(delete_commands);
run_shell_command(next_command, 1);
}
}
void run_shell_command(char* command, int free_command_str)
@ -1039,7 +1016,6 @@ list* get_all_sections_of_type(struct uci_context *ctx, char* package, char* sec
return sections_of_type;
}
char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_name, char* option_name)
{
char* option_value = NULL;
@ -1063,9 +1039,6 @@ char* get_uci_option(struct uci_context* ctx, char* package_name, char* section_
return option_value;
}
// this function dynamically allocates memory for
// the option string, but since this program exits
// almost immediately (after printing variable info)
@ -1101,5 +1074,3 @@ char* get_option_value_string(struct uci_option* uopt)
return opt_str;
}

View File

@ -1,44 +1,32 @@
#
#
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# $Id: Makefile 9907 2007-12-25 01:59:55Z nbd $
include $(TOPDIR)/rules.mk
PKG_NAME:=libericstools
PKG_VERSION:=$(GARGOYLE_VERSION)
ifeq ($(GARGOYLE_VERSION),)
PKG_VERSION:=1.0.0
endif
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
PKG_MAINTAINER:=Eric Bishop <eric@gargoyle-router.com>
include $(INCLUDE_DIR)/package.mk
define Package/libericstools
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Erics Tools
URL:=http://www.gargoyle-router.com
MAINTAINER:=Eric Bishop <eric@gargoyle-router.com>
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Erics Tools
URL:=http://www.gargoyle-router.com
endef
define Package/libericstools/description
A bunch of routines/utilities written by Eric Bishop,
a library primarily used in Gargoyle Web Interface for OpenWrt
A bunch of routines/utilities written by Eric Bishop, a library
primarily used in Gargoyle Web Interface for OpenWrt.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)
endef
define Build/Configure
endef
@ -48,7 +36,6 @@ define Build/InstallDev
mkdir -p $(STAGING_DIR)/usr/lib
$(CP) $(PKG_BUILD_DIR)/*.so* $(STAGING_DIR)/usr/lib/
endef
define Package/libericstools/install

View File

@ -1,35 +1,26 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=qos-gargoyle
PKG_VERSION:=$(GARGOYLE_VERSION)
ifeq ($(GARGOYLE_VERSION),)
PKG_VERSION:=1.0.0
endif
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_MAINTAINER:=Eric Bishop <eric@gargoyle-router.com>
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/kernel.mk
define Package/qos-gargoyle
SECTION:=net
CATEGORY:=Network
TITLE:=A set of QoS scripts designed for use with Gargoyle Web Interface
DEPENDS:=+tc +ip +kmod-sched +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-imq +gargoyle-firewall-util
MAINTAINER:=Eric Bishop <eric@gargoyle-router.com>
SECTION:=net
CATEGORY:=Network
TITLE:=QoS scripts for Gargoyle Web Interface
DEPENDS:=+tc +ip +kmod-sched +iptables-mod-filter +iptables-mod-ipopt \
+iptables-mod-imq +gargoyle-firewall-util
endef
define Package/qos-gargoyle/description
A set of QoS scripts designed for use with Gargoyle Web Interface
A set of QoS scripts designed for use with Gargoyle Web Interface
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
@ -41,22 +32,19 @@ define Build/Compile
LDFLAGS="$(TARGET_LDFLAGS) -L $(STAGING_DIR)/usr/lib" \
BUILD_DIR="$(KERNEL_BUILD_DIR)" \
all
endef
define Package/qos-gargoyle/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_BIN) ./files/qos_gargoyle.init $(1)/etc/init.d/qos_gargoyle
$(INSTALL_BIN) ./files/qos_gargoyle.hotplug $(1)/etc/hotplug.d/iface/23-qos_gargoyle
$(INSTALL_DATA) ./files/qos_gargoyle.conf $(1)/etc/config/qos_gargoyle
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/qosmon $(1)/usr/sbin/qosmon
endef
define Package/qos-gargoyle/prerm

View File

@ -8,13 +8,12 @@ TCDIR:=$(STAGING_DIR)/usr/lib/iproute2
LDLIBS += -lm
TCOBJS := $(TCDIR)/tc/tc_util.o
TCOBJS += $(TCDIR)/tc/tc_core.o
TCOBJS += $(TCDIR)/tc/q_hfsc.o
TCOBJS += $(TCDIR)/lib/libnetlink.a
TCOBJS += $(TCDIR)/lib/libutil.a
LDFLAGS += -Wl,-export-dynamic
LDFLAGS += -Wl,-export-dynamic
all: qosmon
@ -33,4 +32,3 @@ uninstall:
clean:
rm -rf *.o *~ .*sw* qosmon

View File

@ -1,10 +1,10 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/* qosmon - An active QoS monitor for gargoyle routers.
/* qosmon - An active QoS monitor for gargoyle routers.
* Created By Paul Bixel
* http://www.gargoyle-router.com
*
*
* Copyright © 2010 by Paul Bixel <pbix@bigfoot.com>
*
*
* This file is free software: you may copy, redistribute and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 of the License, or (at your
@ -18,7 +18,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
*/
#define _GNU_SOURCE 1
#include <stdint.h>
#include <stdio.h>
@ -47,7 +48,6 @@
#include <ncurses.h>
#endif
#define MAXPACKET 100 /* max packet size */
#define BACKGROUND 3 /* Detact and run in the background */
#define ADDENTITLEMENT 4
@ -58,7 +58,7 @@
//The number of arguments needed for two of our kernel calls changed
//in iproute2 after v2.6.29 (not sure when). We will use the new define
//RTNL_FAMILY_MAX to tell us that we are linking against a version of iproute2
//RTNL_FAMILY_MAX to tell us that we are linking against a version of iproute2
//after then and define dump_filter and talk accordingly.
#ifdef RTNL_FAMILY_MAX
#define dump_filter(a,b,c) rtnl_dump_filter(a,b,c)
@ -77,7 +77,6 @@
/* use_names is required when linking to tc_util.o */
bool use_names = false;
u_char packet[MAXPACKET];
int pingflags, options;
@ -94,7 +93,7 @@ int datalen=64-8; /* How much data */
const char usage[] =
"Gargoyle active congestion controller version 2.4\n\n"
"Usage: qosmon [options] pingtime pingtarget bandwidth [pinglimit]\n"
"Usage: qosmon [options] pingtime pingtarget bandwidth [pinglimit]\n"
" pingtime - The ping interval the monitor will use when active in ms.\n"
" pingtarget - The URL or IP address of the target host for the monitor.\n"
" bandwidth - The maximum download speed the WAN link will support in kbps.\n"
@ -114,7 +113,7 @@ uint16_t nreceived = 0; /* # of packets we got back */
// For our digital filters we use Y = Y(-1) + alpha * (X - Y(-1))
// where alpha = Sample_Period / (TC + Sample_Period)
int fil_triptime; //Filter ping times in uS
int fil_triptime; //Filter ping times in uS
int alpha; //Actually alpha * 1000
int period; //PING period In milliseconds
int rawfltime; //Trip time in milliseconds
@ -144,7 +143,7 @@ u_char firstflg=1; //First pass flag
u_char DCA; //Number of download classes active
u_char RTDCA; //Number of realtime download classes active
u_char pingon=0; //Set to one when pinger becomes active.
int pinglimit=0; //MinRTT mode ping time.
int pinglimit=0; //MinRTT mode ping time.
int pinglimit_cl=0; //Ping limit entered on the commandline.
int plimit; //Currently enforce ping limit
@ -162,6 +161,7 @@ long int dbw_fil; //Filtered total download load (bps).
#define QMON_REALTIME 3
#define QMON_IDLE 4
#define QMON_EXIT 5
char *statename[]= {"CHECK","INIT","ACTIVE","MINRTT","IDLE","DISABLED"};
unsigned char qstate=QMON_CHK;
@ -169,8 +169,8 @@ u_short cnt_mismatch=0;
u_short cnt_errorflg=0;
u_short last_errorflg=0;
FILE *statusfd; //Filestream for updating our status to.
char sigterm=0; //Set when we get a signal to terminal
FILE *statusfd; //Filestream for updating our status to.
char sigterm=0; //Set when we get a signal to terminal
int sel_err=0; //Last error code returned by select
#define DAEMON_NAME "qosmon"
@ -210,8 +210,6 @@ double ceil(double x)
return i;
}
/*
* F I N I S H
*
@ -265,7 +263,7 @@ int in_cksum(u_short *addr, int len)
/*
* P I N G E R
*
*
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
* and the sequence number is an ascending integer. The first 8 bytes
@ -298,15 +296,14 @@ void pinger(void)
/* cc = sendto(s, msg, len, flags, to, tolen) */
i = sendto( s, outpack, cc, 0, (const struct sockaddr *) &whereto, sizeof(whereto) );
}
}
/*
* T V S U B
*
*
* Subtract 2 timeval structs: out = out - in.
*
*
* Out is assumed to be >= in.
*/
void tvsub(register struct timeval *out, register struct timeval *in)
@ -358,14 +355,14 @@ char pr_pack( void *buf, int cc, struct sockaddr_in *from )
//If it was not the packet we are looking for return now.
if (icp->icmp_seq != ntransmitted) return 0;
tp = (struct timeval *)&icp->icmp_data[0];
tvsub( &tv, tp );
triptime = tv.tv_sec*1000+(tv.tv_usec/1000);
//We are now ready to update the filtered round trip time.
//Check for some possible errors first.
if (triptime > period) triptime = period;
if (triptime > period) triptime = period;
//If this was the most recent one we sent then update the rawfltime.
rawfltime=triptime;
@ -375,7 +372,6 @@ char pr_pack( void *buf, int cc, struct sockaddr_in *from )
//return 1 if we got a valid time.
return 1;
}
//These variables referenced but not used by the tc code we link to.
@ -383,7 +379,6 @@ int filter_ifindex;
int use_iec = 0;
int resolve_hosts = 0;
int print_class(struct nlmsghdr *n, void *arg)
{
struct tcmsg *t = NLMSG_DATA(n);
@ -417,14 +412,14 @@ int print_class(struct nlmsghdr *n, void *arg)
//We only deal with hfsc classes.
if (strcmp((char*)RTA_DATA(tb[TCA_KIND]),"hfsc")) return 0;
//Reject the root node
if (t->tcm_parent == TC_H_ROOT) return 0;
//A previous error backs us out.
if (errorflg) return 0;
//If something has changed about the class structure or we reached the
//If something has changed about the class structure or we reached the
//end of the array we need to reset and back out.
if (classcnt >= STATCNT) {
errorflg=1;
@ -441,12 +436,12 @@ int print_class(struct nlmsghdr *n, void *arg)
errorflg=1;
return 0;
}
//First time through so record the ID.
if (firstflg) {
classptr->ID = leafid;
}
classptr->ID = leafid;
}
//Pickup some hfsc basic stats
if (tb[TCA_STATS2]) {
@ -476,7 +471,6 @@ int print_class(struct nlmsghdr *n, void *arg)
sc = RTA_DATA(tbs[TCA_HFSC_FSC]);
classptr->rtclass |= (sc && sc->m1);
}
}
} else {
@ -484,7 +478,6 @@ int print_class(struct nlmsghdr *n, void *arg)
return 0;
}
//Avoid a big jolt on the first pass.
if (firstflg) {
classptr->bytes = work;
@ -500,10 +493,10 @@ int print_class(struct nlmsghdr *n, void *arg)
if (bperiod<period/2) bperiod=period;
bw = (work - classptr->bytes)*8000/bperiod; //bps per second x 1000 here
//Convert back to bps as part of the filter calculation
//Convert back to bps as part of the filter calculation
classptr->cbw_flt=(bw-classptr->cbw_flt)*BWTC/1000+classptr->cbw_flt;
//A class is considered active if its BW exceeds 4000bps
//A class is considered active if its BW exceeds 4000bps
if ((leafid != -1) && (classptr->cbw_flt > 4000)) {
DCA++;actflg=1;
if (classptr->rtclass) RTDCA++;
@ -514,8 +507,7 @@ int print_class(struct nlmsghdr *n, void *arg)
dbw_fil = 0;
} else {
dbw_fil += classptr->cbw_flt;
}
}
}
classptr->bwtime=newtime.tv_nsec;
@ -559,7 +551,6 @@ int class_list(char *d)
return 0;
}
/*
* tc_class_modify
*
@ -604,7 +595,7 @@ int tc_class_modify(__u32 rate)
return 1;
}
req.t.tcm_parent = handle;
strcpy(k,"hsfc");
addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
@ -624,7 +615,6 @@ int tc_class_modify(__u32 rate)
tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
}
//Communicate our change to the kernel.
ll_init_map(&rth);
@ -633,7 +623,6 @@ int tc_class_modify(__u32 rate)
return 1;
}
if (talk(&rth, &req.n, NULL) < 0)
return 2;
@ -647,7 +636,6 @@ int tc_class_modify(__u32 rate)
*/
void update_status( FILE* fd )
{
struct CLASS_STATS *cptr=dnstats;
u_char i;
char nstr[10];
@ -655,7 +643,7 @@ void update_status( FILE* fd )
//Link load includes the ping traffic when the pinger is on.
if (pingon) dbw = dbw_fil + 64 * 8 * 1000/period;
else dbw = dbw_fil;
else dbw = dbw_fil;
//Update the status file.
rewind(fd);
@ -675,8 +663,7 @@ void update_status( FILE* fd )
fprintf(fd,"RTT time limit: %d (ms) [%d/%d]\n",plimit/1000,pinglimit/1000,(pinglimit+135*pinglimit_cl/100)/1000);
fprintf(fd,"Classes Active: %u\n",DCA);
fprintf(fd,"Errors: (mismatch,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err);
fprintf(fd,"Errors: (mismatch,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err);
i=0;
while ((i++<STATCNT) && (cptr->ID != 0)) {
@ -705,16 +692,16 @@ void update_status( FILE* fd )
printw("ping (%s/%d) DCA=%d, RTDCA=%d, plim=%d, plim2=%d, state=%s\n",nstr,fil_triptime/1000,
DCA,RTDCA,pinglimit/1000,plimit/1000,statename[qstate]);
printw("Link Limit=%6d, Fair Limit=%6d, Current Load=%6d (kbps)\n",
printw("Link Limit=%6d, Fair Limit=%6d, Current Load=%6d (kbps)\n",
dbw_ul/1000,new_dbw_ul/1000,dbw/1000);
printw("Saved Active Limit=%6d, Saved Realtime Limit=%6d\n",saved_active_limit/1000,saved_realtime_limit/1000);
printw("pings sent=%d, pings received=%d\n",
printw("pings sent=%d, pings received=%d\n",
ntransmitted,nreceived);
printw("Defined classes for %s\n",DEVICE);
printw("Errors: (mismatches,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err);
printw("Defined classes for %s\n",DEVICE);
printw("Errors: (mismatches,errors,last err,selerr): %u,%u,%u,%i\n", cnt_mismatch, cnt_errorflg,last_errorflg,sel_err);
cptr=dnstats;
i=0;
i=0;
while ((i++<STATCNT) && (cptr->ID != 0)) {
printw("ID %4X, Active %u, Realtime %u. Backlog %u, BW (filtered kbps): %ld\n",
(short unsigned) cptr->ID,
@ -737,7 +724,6 @@ void resetsig(int parm)
resetbw=1;
}
/*
* M A I N
*/
@ -750,7 +736,6 @@ int main(int argc, char *argv[])
struct protoent *proto;
float err;
argc--, av++;
while (argc > 0 && *av[0] == '-') {
while (*++av[0]) switch (*av[0]) {
@ -826,9 +811,9 @@ int main(int argc, char *argv[])
// where alpha = Sample_Period / (TC + Sample_Period)
// TC needs to be not less than 3 times the sample period
alpha = (period*1000. / (period*4 + period));
alpha = (period*1000. / (period*4 + period));
//Class bandwidth filter time constants
//Class bandwidth filter time constants
BWTC= (period*1000. / (7500. + period));
//Check that we have access to tc functions.
@ -840,7 +825,7 @@ int main(int argc, char *argv[])
//Make sure the device is present and that we can scan it.
classptr=dnstats;
errorflg=0;
errorflg=0;
class_list(DEVICE);
if (errorflg) {
fprintf(stderr, "Cannot scan ingress device %s\n",DEVICE);
@ -850,7 +835,7 @@ int main(int argc, char *argv[])
//If running in the background fork()
if (DEAMON) {
/* Ignore most signals in background */
/* Ignore most signals in background */
signal( SIGINT, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
signal( SIGCHLD, SIG_IGN );
@ -891,14 +876,13 @@ int main(int argc, char *argv[])
statusfd = fopen("/tmp/qosmon.status","w");
s = socket(AF_INET, SOCK_RAW, proto->p_proto);
//Check that things opened correctly.
if (DEAMON) {
if (statusfd == NULL) {
syslog( LOG_CRIT, "Cannot open /tmp/qosmon.status - %i",errno );
exit(EXIT_FAILURE);
}
if (s < 0) {
syslog( LOG_CRIT, "Cannot open ping socket - %i",errno );
exit(EXIT_FAILURE);
@ -913,16 +897,16 @@ int main(int argc, char *argv[])
fprintf(stderr, "Cannot open /tmp/qosmon.status - %i",errno );
exit(EXIT_FAILURE);
}
if (s < 0) {
fprintf( stderr, "Cannot open ping socket - %i",errno );
exit(EXIT_FAILURE);
}
//Ctrl-C terminates
//Ctrl-C terminates
signal( SIGINT, (sighandler_t) finish );
//Close terminal terminates
//Close terminal terminates
signal( SIGHUP, (sighandler_t) finish );
setlinebuf( stdout );
@ -957,27 +941,27 @@ int main(int argc, char *argv[])
//Send the next ping
if (pingon) pinger();
//Wait for the pong(s).
timeout.tv_sec = 0;
timeout.tv_usec = period*1000;
//Need a loop here to clean out any old pongs that show up.
//select() returns 1 if there is data to read.
// 0 if the time has expired.
// -1 if a signal arrived.
// -1 if a signal arrived.
while (sel_err=select(s+1, &fdmask, NULL, NULL, &timeout)) {
//Signal arrived, just loop and keep waiting.
if (sel_err == -1) continue;
//If we got here then data must be waiting, try to read the whole packet
if ( (cc=recvfrom(s,packet,len,0,(struct sockaddr *) &from, &fromlen)) < 0) {
continue;
}
//OK there is a whole packet, get it and record the triptime.
pr_pack( packet, cc, &from );
//OK there is a whole packet, get it and record the triptime.
pr_pack( packet, cc, &from );
}
@ -985,7 +969,7 @@ int main(int argc, char *argv[])
classptr=dnstats;
cc=classcnt;
classcnt=0;
errorflg=0;
errorflg=0;
class_list(DEVICE);
//If there was an error or the number of classes changed then reset everything
@ -996,11 +980,10 @@ int main(int argc, char *argv[])
firstflg=1;
pingon=0;
qstate=QMON_CHK;
qstate=QMON_CHK;
continue;
}
//Initialize or reinitialize the fair linklimit.
if (resetbw) {
saved_realtime_limit=saved_active_limit=new_dbw_ul= DBW_UL * .9;
@ -1018,26 +1001,26 @@ int main(int argc, char *argv[])
//Update the filtered ping response time based on what happened.
//If we are not pinging then no change in the filtered value.
if (pingon)
if (pingon)
fil_triptime = ((rawfltime*1000 - fil_triptime)*alpha)/1000 + fil_triptime;
//Run the state machine
switch (qstate) {
// Wait to see if the ping targer will respond at all before doing anything
case QMON_CHK:
case QMON_CHK:
pingon=1;
//If we get two pings go ahead and lower the link speed.
if (nreceived >= 2) {
//If the pinglimit was entered on the command line
//without the add flag then go directly to the
//IDLE state otherwise automatically determine an appropriate
//If the pinglimit was entered on the command line
//without the add flag then go directly to the
//IDLE state otherwise automatically determine an appropriate
//ping limit.
if ((pinglimit) && !(pingflags & ADDENTITLEMENT)) {
dbw_ul=0; //Forces an update in tc_class_modify()
tc_class_modify(new_dbw_ul);
tc_class_modify(new_dbw_ul);
fil_triptime = rawfltime*1000;
qstate=QMON_IDLE;
} else {
@ -1045,8 +1028,8 @@ int main(int argc, char *argv[])
nreceived=0;
qstate=QMON_INIT;
}
}
break;
}
break;
// Take a measurement of the practical ping time we can expect in an unsaturated
// link. We do this by making pings and using the filter response after
@ -1058,7 +1041,7 @@ int main(int argc, char *argv[])
if (nreceived < (10000/period)+1) fil_triptime = rawfltime*1000;
//After 15 seconds we have measured our ping response entitlement.
//Move on to the active state.
//Move on to the active state.
if (nreceived > (15000/period)+1) {
qstate=QMON_IDLE;
tc_class_modify(new_dbw_ul); //Restore reasonable bandwidth
@ -1069,7 +1052,7 @@ int main(int argc, char *argv[])
//Add what the user specified to the 110% of the measure ping time.
pinglimit += (fil_triptime*1.1);
} else {
//Without the '-a' flag we just use 200% of measure ping time.
//Without the '-a' flag we just use 200% of measure ping time.
//This works OK in my system but I have no evidence that it will work in other systems.
pinglimit = fil_triptime*2.0;
}
@ -1078,7 +1061,7 @@ int main(int argc, char *argv[])
if (pinglimit < 10000) pinglimit=10000;
if (pinglimit > 800000) pinglimit=800000;
//Reasonable max ping.
//Reasonable max ping.
rawfltime_max = 2*pinglimit;
}
break;
@ -1100,7 +1083,7 @@ int main(int argc, char *argv[])
if (dbw_fil < 0.12 * DBW_UL) break;
// In the ACTIVE & REALTIME states we observe ping times as long as the
// link remains active. While we are observing we adjust the
// link remains active. While we are observing we adjust the
// link upper limit speed to maintain the specified pinglimit.
// If the amount of data we are recieving dies down we enter the WAIT state
case QMON_ACTIVE:
@ -1113,9 +1096,9 @@ int main(int argc, char *argv[])
//The pinglimit we will use depends on if any realtime classes are active
//or not. In realtime mode we only allow 'pinglimit' round trip times which
//makes our pings low but also lowers our throughput. The automatic measurement
//makes our pings low but also lowers our throughput. The automatic measurement
//above set pinglimit to the average RTT of the ping assuming it has to wait on
//average for 2/3 of an single MTU sized packet to transmit. The means on
//average for 2/3 of an single MTU sized packet to transmit. The means on
//average there is nothing in the buffer but a packet is transmitting.
//When not in realtime mode the stradegy is that we allow enough packets in the queue
@ -1123,32 +1106,32 @@ int main(int argc, char *argv[])
//We are talking about a queue controlled by the ISP so we don't know much about it.
//We make an assumption that the queue is long enough to allow full utilization of the link.
//This should be the case and often the queue is much longer than needed (bufferbloat).
//When not in realtime mode we can allow this buffer to fill but we don't want it to overflow
//This should be the case and often the queue is much longer than needed (bufferbloat).
//When not in realtime mode we can allow this buffer to fill but we don't want it to overflow
//because it will then drop packets which will cause our QoS to breakdown. So we want it to fill
//just enough to promote full link utilization.
//The classical optimum queue size would be equal to the bandwidth * RTT and the
//additional time it will take our ping to pass through such a queue turns out to be the RTT.
//But Barman et all, Globecomm2004 indicates that only 20-30% of this is really needed.
//The classical optimum queue size would be equal to the bandwidth * RTT and the
//additional time it will take our ping to pass through such a queue turns out to be the RTT.
//But Barman et all, Globecomm2004 indicates that only 20-30% of this is really needed.
//
//When we measured an RTT above that it was to the ISPs gateway so we do not really know what the average
//When we measured an RTT above that it was to the ISPs gateway so we do not really know what the average
//RTT time to other IPs on the internet. And since not all hosts respond the same anyway I doubt there
//is consistant RTT that we could use.
//
//For ACTIVE mode on a 925kbps/450kbps link I measured the following
//
//For ACTIVE mode on a 925kbps/450kbps link I measured the following
//relationship between ping limit and throughput with large packets downloading.
//
//Ping Limit Throughput Percent
// 612ms 918kbps 100
// 612ms 918kbps 100
// 525ms 915kbps 99.6
// 437ms 898kbps 97.8
// 350ms 875kbps 95.3
// 262ms 862kbps 93.8
// 350ms 875kbps 95.3
// 262ms 862kbps 93.8
// 81ms 870kbps 94.7
// 60ms 680kbps 69.8
// 50ms 630kbps 68.6
// 40ms 490kbps 53.3
// 40ms 490kbps 53.3
//
//The 1500 byte packet time is 1500*10/925kbps download and 1500*10/425kbps upload for a total
//RTT of around 48ms. Idle ping times on this link are around 35ms.
@ -1199,7 +1182,7 @@ int main(int argc, char *argv[])
//Do not increase the bandwidth until we reach 85% of the current limit.
if (dbw_fil < dbw_ul * 0.85) break;
//Increase slowly (0.4%/sec). err is negative here.
//Increase slowly (0.4%/sec). err is negative here.
new_dbw_ul = new_dbw_ul * (1.0 - 0.004*err*(float)period/(float)plimit/1000.0);
if (new_dbw_ul > DBW_UL) new_dbw_ul=DBW_UL;
@ -1208,9 +1191,9 @@ int main(int argc, char *argv[])
new_dbw_ul = new_dbw_ul * (1.0 - 0.004*err*(float)period/(float)plimit/1000.0);
//Dynamic range is 1/.15 or 6.67 : 1.
//Dynamic range is 1/.15 or 6.67 : 1.
if (new_dbw_ul < DBW_UL*.15) new_dbw_ul=DBW_UL*.15;
}
}
//Modify parent download limit as needed.
tc_class_modify(new_dbw_ul);
@ -1219,38 +1202,34 @@ int main(int argc, char *argv[])
if (rawfltime_max > plimit) rawfltime_max -= 100;
break;
}
update_status(statusfd);
//If we get here the first pass is over.
//If we get here the first pass is over.
firstflg=0;
} //Next ping
} //Next ping
qstate=QMON_EXIT;
//We got a signal to terminate so start by restoring the root TC class to
//the original upper limit.
tc_class_modify(DBW_UL);
update_status(statusfd);
//Write a message in the system log
if (DEAMON) {
syslog( LOG_NOTICE, "terminated sigterm=%i, sel_err=%i", sigterm, sel_err );
closelog();
}
}
#ifndef ONLYBG
else {
else {
endwin();
fflush(stdout);
}
#endif
}