From: fendo Date: Mon, 7 Oct 2013 20:49:53 +0000 (+0200) Subject: Merge from master X-Git-Tag: 2.2.1-2sames3.12 X-Git-Url: http://git.sameswireless.fr/l2tpns.git/commitdiff_plain/30b561eb71683b52894abacf0a607d7d6932e4c1?hp=-c Merge from master --- 30b561eb71683b52894abacf0a607d7d6932e4c1 diff --combined Makefile index b19dfcd,fb12741..7280139 --- a/Makefile +++ b/Makefile @@@ -18,15 -18,15 +18,15 @@@ CC = gc LD = gcc INCLUDES = -I. CPPFLAGS = $(INCLUDES) $(DEFINES) - CFLAGS = -Wall -Wformat-security -Wno-format-zero-length $(OPTIM) + CFLAGS = -Wall -Wformat-security $(OPTIM) LDFLAGS = LDLIBS = INSTALL = install -c -D -o root -g root - l2tpns.LIBS = -lm -lcli -ldl + l2tpns.LIBS = -lcli -ldl OBJS = arp.o cli.o cluster.o constants.o control.o icmp.o l2tpns.o \ - ll.o md5.o ppp.o radius.o tbf.o util.o pppoe.o l2tplac.o + ll.o md5.o ppp.o radius.o tbf.o util.o pppoe.o l2tplac.o grpsess.o PROGRAMS = l2tpns nsctl PLUGINS = autosnoop.so autothrottle.so garden.so sessionctl.so \ @@@ -127,7 -127,6 +127,7 @@@ tbf.o: tbf.c l2tpns.h util.h tbf. util.o: util.c l2tpns.h bgp.h pppoe.o: pppoe.c l2tpns.h cluster.h constants.h md5.h util.h l2tplac.o: l2tplac.c md5.h l2tpns.h util.h cluster.h l2tplac.h pppoe.h +grpsess.o: grpsess.c l2tpns.h util.h cluster.h bgp.h bgp.o: bgp.c l2tpns.h bgp.h util.h autosnoop.so: autosnoop.c l2tpns.h plugin.h autothrottle.so: autothrottle.c l2tpns.h plugin.h diff --combined cli.c index e5ac57c,f280330..876ad06 --- a/cli.c +++ b/cli.c @@@ -21,7 -21,6 +21,7 @@@ #include #include #include +#include #include "l2tpns.h" #include "constants.h" @@@ -75,61 -74,60 +75,61 @@@ static char *debug_levels[] = #endif - static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_group(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_tunnels(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_users(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_radius(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_version(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_pool(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_banana(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_plugins(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_throttle(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_write_memory(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_drop_user(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_drop_tunnel(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_drop_session(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_snoop(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_no_snoop(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_throttle(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_no_throttle(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_debug(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_no_debug(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_set(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_load_plugin(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_remove_plugin(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_uptime(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_shutdown(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_reload(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_setforward(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_rmtlnsconf(struct cli_def *cli, char *command, char **argv, int argc); + static int cmd_show_session(struct cli_def *cli, const char *command, char **argv, int argc); ++static int cmd_show_group(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_tunnels(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_users(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_radius(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_version(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_pool(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_run(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_banana(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_plugins(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_throttle(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_write_memory(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_drop_user(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_drop_tunnel(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_drop_session(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_snoop(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_no_snoop(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_throttle(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_no_throttle(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_debug(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_no_debug(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_set(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_load_plugin(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_remove_plugin(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_uptime(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_shutdown(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_reload(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_setforward(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_rmtlnsconf(struct cli_def *cli, const char *command, char **argv, int argc); static int regular_stuff(struct cli_def *cli); #ifdef STATISTICS - static int cmd_show_counters(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_clear_counters(struct cli_def *cli, char *command, char **argv, int argc); + static int cmd_show_counters(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_clear_counters(struct cli_def *cli, const char *command, char **argv, int argc); #endif /* STATISTICS */ #ifdef BGP #define MODE_CONFIG_BGP 8 - static int cmd_router_bgp(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_router_bgp_no_neighbour(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_bgp(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_suspend_bgp(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_no_suspend_bgp(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int argc); + static int cmd_router_bgp(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_router_bgp_neighbour(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_router_bgp_no_neighbour(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_bgp(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_suspend_bgp(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_no_suspend_bgp(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_restart_bgp(struct cli_def *cli, const char *command, char **argv, int argc); #endif /* BGP */ #define MODE_CONFIG_NACL 9 - static int cmd_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_no_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_ip_access_list_rule(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_filter(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_no_filter(struct cli_def *cli, char *command, char **argv, int argc); - static int cmd_show_access_list(struct cli_def *cli, char *command, char **argv, int argc); + static int cmd_ip_access_list(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_no_ip_access_list(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_ip_access_list_rule(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_filter(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_no_filter(struct cli_def *cli, const char *command, char **argv, int argc); + static int cmd_show_access_list(struct cli_def *cli, const char *command, char **argv, int argc); /* match if b is a substr of a */ #define MATCH(a,b) (!strncmp((a), (b), strlen(b))) @@@ -156,7 -154,6 +156,7 @@@ void init_cli( cli_register_command(cli, c, "running-config", cmd_show_run, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Show the currently running configuration"); cli_register_command(cli, c, "remotelns-conf", cmd_show_rmtlnsconf, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Show a list of remote LNS configuration"); cli_register_command(cli, c, "session", cmd_show_session, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show a list of sessions or details for a single session"); + cli_register_command(cli, c, "group", cmd_show_group, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show a list of groups or details for a single group"); cli_register_command(cli, c, "tbf", cmd_show_tbf, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "List all token bucket filters in use"); cli_register_command(cli, c, "throttle", cmd_show_throttle, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "List all throttled sessions and associated TBFs"); cli_register_command(cli, c, "tunnels", cmd_show_tunnels, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show a list of tunnels or details for a single tunnel"); @@@ -357,7 -354,7 +357,7 @@@ void cli_do(int sockfd exit(0); } - static void cli_print_log(struct cli_def *cli, char *string) + static void cli_print_log(struct cli_def *cli, const char *string) { LOG(3, 0, 0, "%s\n", string); } @@@ -406,7 -403,7 +406,7 @@@ int cli_arg_help(struct cli_def *cli, i return CLI_OK; } - static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_session(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -585,7 -582,7 +585,7 @@@ return CLI_OK; } - static int cmd_show_tunnels(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_tunnels(struct cli_def *cli, const char *command, char **argv, int argc) { int i, x, show_all = 0; char *states[] = { @@@ -676,7 -673,7 +676,7 @@@ return CLI_OK; } - static int cmd_show_users(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_users(struct cli_def *cli, const char *command, char **argv, int argc) { char sid[32][8]; char *sargv[32]; @@@ -718,7 -715,7 +718,7 @@@ } #ifdef STATISTICS - static int cmd_show_counters(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_counters(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -733,7 -730,7 +733,7 @@@ GET_STAT(tun_tx_bytes), GET_STAT(tun_tx_packets), GET_STAT(tun_tx_errors)); - cli_print(cli, ""); + cli_print(cli, " "); cli_print(cli, "%-10s %10s %10s %10s %10s", "Tunnel", "Bytes", "Packets", "Errors", "Retries"); cli_print(cli, "%-10s %10u %10u %10u", "RX", @@@ -745,7 -742,7 +745,7 @@@ GET_STAT(tunnel_tx_packets), GET_STAT(tunnel_tx_errors), GET_STAT(tunnel_retries)); - cli_print(cli, ""); + cli_print(cli, " "); cli_print(cli, "%-30s%-10s", "Counter", "Value"); cli_print(cli, "-----------------------------------------"); @@@ -811,14 -808,14 +811,14 @@@ char *p = strchr(t, '\n'); if (p) *p = 0; - cli_print(cli, ""); + cli_print(cli, " "); cli_print(cli, "Last counter reset %s", t); } return CLI_OK; } - static int cmd_clear_counters(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_clear_counters(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -831,7 -828,7 +831,7 @@@ } #endif /* STATISTICS */ - static int cmd_show_version(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_version(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -840,7 -837,7 +840,7 @@@ return CLI_OK; } - static int cmd_show_pool(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_pool(struct cli_def *cli, const char *command, char **argv, int argc) { int i; int used = 0, free = 0, show_all = 0; @@@ -902,13 -899,13 +902,13 @@@ } static FILE *save_config_fh = 0; - static void print_save_config(struct cli_def *cli, char *string) + static void print_save_config(struct cli_def *cli, const char *string) { if (save_config_fh) fprintf(save_config_fh, "%s\n", string); } - static int cmd_write_memory(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_write_memory(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -931,7 -928,7 +931,7 @@@ static char const *show_access_list_rule(int extended, ip_filter_rulet *rule); - static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_run(struct cli_def *cli, const char *command, char **argv, int argc) { int i; char ipv6addr[INET6_ADDRSTRLEN]; @@@ -1028,7 -1025,7 +1028,7 @@@ return CLI_OK; } - static int cmd_show_radius(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_radius(struct cli_def *cli, const char *command, char **argv, int argc) { int i, free = 0, used = 0, show_all = 0; char *states[] = { @@@ -1083,7 -1080,7 +1083,7 @@@ return CLI_OK; } - static int cmd_show_plugins(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_plugins(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -1098,7 -1095,7 +1098,7 @@@ return CLI_OK; } - static int cmd_show_throttle(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_throttle(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -1130,7 -1127,7 +1130,7 @@@ return CLI_OK; } - static int cmd_show_banana(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_banana(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -1153,7 -1150,7 +1153,7 @@@ return CLI_OK; } - static int cmd_drop_user(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_drop_user(struct cli_def *cli, const char *command, char **argv, int argc) { int i; sessionidt s; @@@ -1194,7 -1191,7 +1194,7 @@@ return CLI_OK; } - static int cmd_drop_tunnel(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_drop_tunnel(struct cli_def *cli, const char *command, char **argv, int argc) { int i; tunnelidt t; @@@ -1244,7 -1241,7 +1244,7 @@@ return CLI_OK; } - static int cmd_drop_session(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_drop_session(struct cli_def *cli, const char *command, char **argv, int argc) { int i; sessionidt s; @@@ -1294,7 -1291,7 +1294,7 @@@ return CLI_OK; } - static int cmd_snoop(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_snoop(struct cli_def *cli, const char *command, char **argv, int argc) { in_addr_t ip; uint16_t port; @@@ -1367,7 -1364,7 +1367,7 @@@ return CLI_OK; } - static int cmd_no_snoop(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_no_snoop(struct cli_def *cli, const char *command, char **argv, int argc) { int i; sessionidt s; @@@ -1405,7 -1402,7 +1405,7 @@@ return CLI_OK; } - static int cmd_throttle(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_throttle(struct cli_def *cli, const char *command, char **argv, int argc) { int rate_in = 0; int rate_out = 0; @@@ -1533,7 -1530,7 +1533,7 @@@ return CLI_OK; } - static int cmd_no_throttle(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_no_throttle(struct cli_def *cli, const char *command, char **argv, int argc) { int i; sessionidt s; @@@ -1578,7 -1575,7 +1578,7 @@@ return CLI_OK; } - static int cmd_debug(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_debug(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -1642,7 -1639,7 +1642,7 @@@ return CLI_OK; } - static int cmd_no_debug(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_no_debug(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -1688,7 -1685,7 +1688,7 @@@ return CLI_OK; } - static int cmd_load_plugin(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_load_plugin(struct cli_def *cli, const char *command, char **argv, int argc) { int i, firstfree = 0; @@@ -1723,7 -1720,7 +1723,7 @@@ return CLI_OK; } - static int cmd_remove_plugin(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_remove_plugin(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -1784,7 -1781,7 +1784,7 @@@ static char *duration(time_t secs return buf; } - static int cmd_uptime(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_uptime(struct cli_def *cli, const char *command, char **argv, int argc) { FILE *fh; char buf[100], *p = buf, *loads[3]; @@@ -1794,7 -1791,7 +1794,7 @@@ return CLI_HELP_NO_ARGS; fh = fopen("/proc/loadavg", "r"); - fgets(buf, 100, fh); + p = fgets(buf, 100, fh); fclose(fh); for (i = 0; i < 3; i++) @@@ -1820,7 -1817,7 +1820,7 @@@ return CLI_OK; } - static int cmd_set(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_set(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -1949,7 -1946,7 +1949,7 @@@ int regular_stuff(struct cli_def *cli } #ifdef BGP - static int cmd_router_bgp(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_router_bgp(struct cli_def *cli, const char *command, char **argv, int argc) { int as; @@@ -2015,7 -2012,7 +2015,7 @@@ static int find_bgp_neighbour(char cons return new; } - static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_router_bgp_neighbour(struct cli_def *cli, const char *command, char **argv, int argc) { int i; int keepalive; @@@ -2159,7 -2156,7 +2159,7 @@@ return CLI_OK; } - static int cmd_router_bgp_no_neighbour(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_router_bgp_no_neighbour(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -2191,7 -2188,7 +2191,7 @@@ return CLI_OK; } - static int cmd_show_bgp(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_bgp(struct cli_def *cli, const char *command, char **argv, int argc) { int i; int hdr = 0; @@@ -2223,7 -2220,7 +2223,7 @@@ if (!hdr++) { - cli_print(cli, ""); + cli_print(cli, " "); cli_print(cli, "Peer AS Address " "State Retries Retry in Route Pend Timers"); cli_print(cli, "------------------ ----- --------------- " @@@ -2246,7 -2243,7 +2246,7 @@@ return CLI_OK; } - static int cmd_suspend_bgp(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_suspend_bgp(struct cli_def *cli, const char *command, char **argv, int argc) { int i; char *addr; @@@ -2279,7 -2276,7 +2279,7 @@@ return CLI_OK; } - static int cmd_no_suspend_bgp(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_no_suspend_bgp(struct cli_def *cli, const char *command, char **argv, int argc) { int i; char *addr; @@@ -2313,7 -2310,7 +2313,7 @@@ return CLI_OK; } - static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_restart_bgp(struct cli_def *cli, const char *command, char **argv, int argc) { int i; char *addr; @@@ -2441,12 -2438,12 +2441,12 @@@ static int access_list(struct cli_def * return CLI_OK; } - static int cmd_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_ip_access_list(struct cli_def *cli, const char *command, char **argv, int argc) { return access_list(cli, argv, argc, 1); } - static int cmd_no_ip_access_list(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_no_ip_access_list(struct cli_def *cli, const char *command, char **argv, int argc) { return access_list(cli, argv, argc, 0); } @@@ -2532,7 -2529,7 +2532,7 @@@ static char const *show_access_list_rul return buf; } - static ip_filter_rulet *access_list_rule_ext(struct cli_def *cli, char *command, char **argv, int argc) + static ip_filter_rulet *access_list_rule_ext(struct cli_def *cli, const char *command, char **argv, int argc) { static ip_filter_rulet rule; struct in_addr addr; @@@ -2767,7 -2764,7 +2767,7 @@@ return &rule; } - static ip_filter_rulet *access_list_rule_std(struct cli_def *cli, char *command, char **argv, int argc) + static ip_filter_rulet *access_list_rule_std(struct cli_def *cli, const char *command, char **argv, int argc) { static ip_filter_rulet rule; struct in_addr addr; @@@ -2883,7 -2880,7 +2883,7 @@@ return &rule; } - static int cmd_ip_access_list_rule(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_ip_access_list_rule(struct cli_def *cli, const char *command, char **argv, int argc) { int i; ip_filter_rulet *rule = ip_filters[filt].extended @@@ -2909,7 -2906,7 +2909,7 @@@ return CLI_OK; } - static int cmd_filter(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_filter(struct cli_def *cli, const char *command, char **argv, int argc) { sessionidt s; int i; @@@ -3005,7 -3002,7 +3005,7 @@@ return CLI_OK; } - static int cmd_no_filter(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_no_filter(struct cli_def *cli, const char *command, char **argv, int argc) { int i; sessionidt s; @@@ -3050,7 -3047,7 +3050,7 @@@ return CLI_OK; } - static int cmd_show_access_list(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_access_list(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -3095,7 -3092,7 +3095,7 @@@ return CLI_OK; } - static int cmd_shutdown(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_shutdown(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -3104,7 -3101,7 +3104,7 @@@ return CLI_OK; } - static int cmd_reload(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_reload(struct cli_def *cli, const char *command, char **argv, int argc) { if (CLI_HELP_REQUESTED) return CLI_HELP_NO_ARGS; @@@ -3113,78 -3110,7 +3113,78 @@@ return CLI_OK; } - static int cmd_show_group(struct cli_def *cli, char *command, char **argv, int argc) ++static int cmd_show_group(struct cli_def *cli, const char *command, char **argv, int argc) +{ + int i; + groupidt g; + + if (CLI_HELP_REQUESTED) + return cli_arg_help(cli, 1, + "<1-%d>", MAXGROUPE-1, "Show specific group by id", + NULL); + + time(&time_now); + if (argc > 0) + { + // Show individual group + for (i = 0; i < argc; i++) + { + sessionidt s; + + g = atoi(argv[i]); + if (g <= 0 || g >= MAXGROUPE) + { + cli_print(cli, "Invalid group id \"%s\"", argv[i]); + continue; + } + + cli_print(cli, "\r\nGroup %d:", g); + cli_print(cli, "\tNb Session:\t\t%d", grpsession[g].nbsession); + cli_print(cli, "\tNb Routes:\t\t%d", grpsession[g].nbroutesgrp); + cli_print(cli, "\ttime_changed:\t\t%d\n", grpsession[g].time_changed); + + for (i = 0; i < grpsession[g].nbsession; i++) + { + if ((s = grpsession[g].sesslist[i].sid)) + { + cli_print(cli, "\tSession:\t%d\tTx Rate:%d Kbps\t\t\tweight:\t%d", + s, + grpsession[g].sesslist[i].tx_rate/(1024/8), + grpsession[g].sesslist[i].weight); + } + } + + for (i = 0; i < grpsession[g].nbroutesgrp; i++) + { + if (grpsession[g].route[i].ip != 0) + { + cli_print(cli, "\tRoute:\t%s/%d", fmtaddr(htonl(grpsession[g].route[i].ip), 0), grpsession[g].route[i].prefixlen); + } + } + } + return CLI_OK; + } + + // Show Summary + cli_print(cli, "%5s %7s %9s %12s", + "GID", + "Nb Sess", + "Nb Routes", + "Time changed"); + + for (g = gnextgrpid; g != 0; g = grpsession[g].prev) + { + cli_print(cli, "%5d %7d %9d %12d", + g, + grpsession[g].nbsession, + grpsession[g].nbroutesgrp, + grpsession[g].time_changed); + } + + return CLI_OK; +} + - static int cmd_setforward(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_setforward(struct cli_def *cli, const char *command, char **argv, int argc) { int ret; @@@ -3234,7 -3160,7 +3234,7 @@@ return CLI_OK; } - static int cmd_show_rmtlnsconf(struct cli_def *cli, char *command, char **argv, int argc) + static int cmd_show_rmtlnsconf(struct cli_def *cli, const char *command, char **argv, int argc) { confrlnsidt idrlns; char strdisp[1024]; diff --combined cluster.c index fc4d58a,94d0cd0..7768bf2 --- a/cluster.c +++ b/cluster.c @@@ -16,7 -16,6 +16,7 @@@ #include #include #include +#include #include "l2tpns.h" #include "cluster.h" @@@ -44,7 -43,6 +44,7 @@@ in_addr_t my_address = 0; // The netwo static int walk_session_number = 0; // The next session to send when doing the slow table walk. static int walk_bundle_number = 0; // The next bundle to send when doing the slow table walk. static int walk_tunnel_number = 0; // The next tunnel to send when doing the slow table walk. +static int walk_groupe_number = 0; // The next groupe to send when doing the slow table walk. int forked = 0; // Sanity check: CLI must not diddle with heartbeat table #define MAX_HEART_SIZE (8192) // Maximum size of heartbeat packet. Must be less than max IP packet size :) @@@ -89,7 -87,6 +89,7 @@@ int cluster_init( config->cluster_undefined_sessions = MAXSESSION-1; config->cluster_undefined_bundles = MAXBUNDLE-1; config->cluster_undefined_tunnels = MAXTUNNEL-1; + config->cluster_undefined_groupes = MAXGROUPE-1; if (!config->cluster_address) return 0; @@@ -231,8 -228,7 +231,8 @@@ static void cluster_uptodate(void if (config->cluster_iam_uptodate) return; - if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles) + if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || + config->cluster_undefined_bundles || config->cluster_undefined_groupes) return; config->cluster_iam_uptodate = 1; @@@ -457,8 -453,7 +457,8 @@@ void cluster_send_ping(time_t basetime x.ver = 1; x.addr = config->bind_address; - x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels + config->cluster_undefined_bundles; + x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels + + config->cluster_undefined_groupes + config->cluster_undefined_bundles; x.basetime = basetime; add_type(&p, C_PING, basetime, (uint8_t *) &x, sizeof(x)); @@@ -680,20 -675,6 +680,20 @@@ void cluster_check_master(void config->cluster_highest_bundleid = i; } + // + // Go through and mark all the groupes as defined. + // Count the highest used groupe number as well. + // + config->cluster_highest_groupeid = 0; + for (i = 0; i < MAXGROUPE; ++i) + { + if (grpsession[i].state == GROUPEUNDEF) + grpsession[i].state = GROUPEFREE; + + if (grpsession[i].state != GROUPEFREE && i > config->cluster_highest_groupeid) + config->cluster_highest_groupeid = i; + } + // // Go through and mark all the sessions as being defined. // reset the idle timeouts. @@@ -761,7 -742,6 +761,7 @@@ config->cluster_undefined_sessions = 0; config->cluster_undefined_bundles = 0; config->cluster_undefined_tunnels = 0; + config->cluster_undefined_groupes = 0; config->cluster_iam_uptodate = 1; // assume all peers are up-to-date // FIXME. We need to fix up the tunnel control message @@@ -778,7 -758,7 +778,7 @@@ // we fix it up here, and we ensure that the 'first free session' // pointer is valid. // -static void cluster_check_sessions(int highsession, int freesession_ptr, int highbundle, int hightunnel) +static void cluster_check_sessions(int highsession, int freesession_ptr, int highbundle, int hightunnel, int highgroupe) { int i; @@@ -787,8 -767,7 +787,8 @@@ if (config->cluster_iam_uptodate) return; - if (highsession > config->cluster_undefined_sessions && highbundle > config->cluster_undefined_bundles && hightunnel > config->cluster_undefined_tunnels) + if (highsession > config->cluster_undefined_sessions && highbundle > config->cluster_undefined_bundles && + highgroupe > config->cluster_undefined_groupes && hightunnel > config->cluster_undefined_tunnels) return; // Clear out defined sessions, counting the number of @@@ -830,23 -809,10 +830,23 @@@ ++config->cluster_undefined_tunnels; } + // Clear out defined groupe, counting the number of + // undefs remaining. + config->cluster_undefined_groupes = 0; + for (i = 1 ; i < MAXGROUPE; ++i) { + if (i > highgroupe) { + if (grpsession[i].state == GROUPEUNDEF) grpsession[i].state = GROUPEFREE; // Defined. + continue; + } + + if (grpsession[i].state == GROUPEUNDEF) + ++config->cluster_undefined_groupes; + } - if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles) { - LOG(2, 0, 0, "Cleared undefined sessions/bundles/tunnels. %d sess (high %d), %d bund (high %d), %d tunn (high %d)\n", - config->cluster_undefined_sessions, highsession, config->cluster_undefined_bundles, highbundle, config->cluster_undefined_tunnels, hightunnel); + if (config->cluster_undefined_sessions || config->cluster_undefined_tunnels || config->cluster_undefined_bundles || config->cluster_undefined_groupes) { + LOG(2, 0, 0, "Cleared undefined sessions/bundles/tunnels. %d sess (high %d), %d bund (high %d), %d grp (high %d), %d tunn (high %d)\n", + config->cluster_undefined_sessions, highsession, config->cluster_undefined_bundles, highbundle, + config->cluster_undefined_groupes, highgroupe, config->cluster_undefined_tunnels, hightunnel); return; } @@@ -900,27 -866,6 +900,27 @@@ static int hb_add_type(uint8_t **p, in add_type(p, C_BUNDLE, id, (uint8_t *) &bundle[id], sizeof(bundlet)); break; + case C_CGROUPE: { // Compressed C_GROUPE + uint8_t c[sizeof(groupsesst) * 2]; // Bigger than worst case. + uint8_t *d = (uint8_t *) &grpsession[id]; + uint8_t *orig = d; + int size; + + size = rle_compress( &d, sizeof(groupsesst), c, sizeof(c) ); + + // Did we compress the full structure, and is the size actually + // reduced?? + if ( (d - orig) == sizeof(groupsesst) && size < sizeof(groupsesst) ) + { + add_type(p, C_CGROUPE, id, c, size); + break; + } + // Failed to compress : Fall through. + } + case C_GROUPE: + add_type(p, C_GROUPE, id, (uint8_t *) &grpsession[id], sizeof(groupsesst)); + break; + case C_CTUNNEL: { // Compressed C_TUNNEL uint8_t c[sizeof(tunnelt) * 2]; // Bigger than worst case. uint8_t *d = (uint8_t *) &tunnel[id]; @@@ -953,7 -898,7 +953,7 @@@ // void cluster_heartbeat() { - int i, count = 0, tcount = 0, bcount = 0; + int i, count = 0, tcount = 0, bcount = 0, gcount = 0; uint8_t buff[MAX_HEART_SIZE + sizeof(heartt) + sizeof(int) ]; heartt h; uint8_t *p = buff; @@@ -975,11 -920,9 +975,11 @@@ h.freesession = sessionfree; h.hightunnel = config->cluster_highest_tunnelid; h.highbundle = config->cluster_highest_bundleid; + h.highgroupe = config->cluster_highest_groupeid; h.size_sess = sizeof(sessiont); // Just in case. h.size_bund = sizeof(bundlet); h.size_tunn = sizeof(tunnelt); + h.nextgrpid = gnextgrpid; h.interval = config->cluster_hb_interval; h.timeout = config->cluster_hb_timeout; h.table_version = config->cluster_table_version; @@@ -998,7 -941,7 +998,7 @@@ // // Fill out the packet with sessions from the session table... - // (not forgetting to leave space so we can get some tunnels in too ) + // (not forgetting to leave space so we can get some tunnels,bundle,groupe in too ) while ( (p + sizeof(uint32_t) * 2 + sizeof(sessiont) * 2 ) < (buff + MAX_HEART_SIZE) ) { if (!walk_session_number) // session #0 isn't valid. @@@ -1013,59 -956,40 +1013,59 @@@ ++count; // Count the number of extra sessions we're sending. } - // - // Fill out the packet with tunnels from the tunnel table... - // This effectively means we walk the tunnel table more quickly - // than the session table. This is good because stuffing up a - // tunnel is a much bigger deal than stuffing up a session. - // - while ( (p + sizeof(uint32_t) * 2 + sizeof(tunnelt) ) < (buff + MAX_HEART_SIZE) ) { + // + // Fill out the packet with tunnels from the tunnel table... + // This effectively means we walk the tunnel table more quickly + // than the session table. This is good because stuffing up a + // tunnel is a much bigger deal than stuffing up a session. + // + int maxsize = (sizeof(tunnelt) < sizeof(bundlet)) ? sizeof(bundlet):sizeof(tunnelt); + maxsize = (sizeof(groupsesst) < maxsize) ? maxsize:sizeof(groupsesst); + maxsize += (sizeof(uint32_t) * 2); + + // Fill out the packet with tunnels,bundlets, groupes from the tables... + while ( (p + maxsize) < (buff + MAX_HEART_SIZE) ) + { + if ((tcount >= config->cluster_highest_tunnelid) && + (bcount >= config->cluster_highest_bundleid) && + (gcount >= config->cluster_highest_groupeid)) + break; - if (!walk_tunnel_number) // tunnel #0 isn't valid. - ++walk_tunnel_number; + if ( ((p + sizeof(uint32_t) * 2 + sizeof(tunnelt) ) < (buff + MAX_HEART_SIZE)) && + (tcount < config->cluster_highest_tunnelid)) + { + if (!walk_tunnel_number) // tunnel #0 isn't valid. + ++walk_tunnel_number; - if (tcount >= config->cluster_highest_tunnelid) - break; + hb_add_type(&p, C_CTUNNEL, walk_tunnel_number); + walk_tunnel_number = (1+walk_tunnel_number)%(config->cluster_highest_tunnelid+1); // +1 avoids divide by zero. - hb_add_type(&p, C_CTUNNEL, walk_tunnel_number); - walk_tunnel_number = (1+walk_tunnel_number)%(config->cluster_highest_tunnelid+1); // +1 avoids divide by zero. + ++tcount; + } - ++tcount; - } + if ( ((p + sizeof(uint32_t) * 2 + sizeof(bundlet) ) < (buff + MAX_HEART_SIZE)) && + (bcount < config->cluster_highest_bundleid)) + { + if (!walk_bundle_number) // bundle #0 isn't valid. + ++walk_bundle_number; - // - // Fill out the packet with bundles from the bundle table... - while ( (p + sizeof(uint32_t) * 2 + sizeof(bundlet) ) < (buff + MAX_HEART_SIZE) ) { + hb_add_type(&p, C_CBUNDLE, walk_bundle_number); + walk_bundle_number = (1+walk_bundle_number)%(config->cluster_highest_bundleid+1); // +1 avoids divide by zero. - if (!walk_bundle_number) // bundle #0 isn't valid. - ++walk_bundle_number; + ++bcount; + } - if (bcount >= config->cluster_highest_bundleid) - break; + if ( ((p + sizeof(uint32_t) * 2 + sizeof(groupsesst) ) < (buff + MAX_HEART_SIZE)) && + (gcount < config->cluster_highest_groupeid)) + { + if (!walk_groupe_number) // groupe #0 isn't valid. + ++walk_groupe_number; - hb_add_type(&p, C_CBUNDLE, walk_bundle_number); - walk_bundle_number = (1+walk_bundle_number)%(config->cluster_highest_bundleid+1); // +1 avoids divide by zero. - ++bcount; - } + hb_add_type(&p, C_CGROUPE, walk_groupe_number); + walk_groupe_number = (1+walk_groupe_number)%(config->cluster_highest_groupeid+1); // +1 avoids divide by zero. + ++gcount; + } + } // // Did we do something wrong? @@@ -1076,10 -1000,10 +1076,10 @@@ } LOG(4, 0, 0, "Sending v%d heartbeat #%d, change #%" PRIu64 " with %d changes " - "(%d x-sess, %d x-bundles, %d x-tunnels, %d highsess, %d highbund, %d hightun, size %d)\n", + "(%d x-sess, %d x-bundles, %d x-tunnels, %d x-groupes, %d highsess, %d highbund, %d hightun, %d highgrp, size %d)\n", HB_VERSION, h.seq, h.table_version, config->cluster_num_changes, - count, bcount, tcount, config->cluster_highest_sessionid, config->cluster_highest_bundleid, - config->cluster_highest_tunnelid, (int) (p - buff)); + count, bcount, tcount, gcount, config->cluster_highest_sessionid, config->cluster_highest_bundleid, + config->cluster_highest_tunnelid, config->cluster_highest_groupeid, (int) (p - buff)); config->cluster_num_changes = 0; @@@ -1145,18 -1069,6 +1145,18 @@@ int cluster_send_bundle(int bid return type_changed(C_CBUNDLE, bid); } +// A particular groupe has been changed! +int cluster_send_groupe(int gid) +{ + if (!config->cluster_iam_master) + { + LOG(0, 0, gid, "I'm not a master, but I just tried to change a groupe!\n"); + return -1; + } + + return type_changed(C_CGROUPE, gid); +} + // A particular tunnel has been changed! int cluster_send_tunnel(int tid) { @@@ -1421,31 -1333,6 +1421,31 @@@ static int cluster_recv_bundle(int more return 0; } +static int cluster_recv_groupe(int more, uint8_t *p) +{ + if (more >= MAXGROUPE) { + LOG(0, 0, 0, "DANGER: Received a group id > MAXGROUPE!\n"); + return -1; + } + + if (grpsession[more].state == GROUPEUNDEF) { + if (config->cluster_iam_uptodate) { // Sanity. + LOG(0, 0, 0, "I thought I was uptodate but I just found an undefined group!\n"); + } else { + --config->cluster_undefined_groupes; + } + } + + grp_cluster_load_groupe(more, (groupsesst *) p); // Copy groupe into groupe table.. + + LOG(5, 0, more, "Received group update (%d undef)\n", config->cluster_undefined_groupes); + + if (!config->cluster_iam_uptodate) + cluster_uptodate(); // Check to see if we're up to date. + + return 0; +} + static int cluster_recv_tunnel(int more, uint8_t *p) { if (more >= MAXTUNNEL) { @@@ -1742,10 -1629,9 +1742,10 @@@ static int cluster_process_heartbeat(ui memcpy(&past_hearts[i].data, data, size); // Save it. - // Check that we don't have too many undefined sessions, and - // that the free session pointer is correct. - cluster_check_sessions(h->highsession, h->freesession, h->highbundle, h->hightunnel); + // Check that we don't have too many undefined sessions, and + // that the free session pointer is correct. + gnextgrpid = h->nextgrpid; + cluster_check_sessions(h->highsession, h->freesession, h->highbundle, h->hightunnel, h->highgroupe); if (h->interval != config->cluster_hb_interval) { @@@ -1883,36 -1769,6 +1883,36 @@@ p += sizeof(bundle[more]); s -= sizeof(bundle[more]); break; + + case C_CGROUPE: + { // Compressed Groupe structure. + uint8_t c[ sizeof(groupsesst) + 2]; + int size; + uint8_t *orig_p = p; + + size = rle_decompress((uint8_t **) &p, s, c, sizeof(c)); + s -= (p - orig_p); + + if (size != sizeof(groupsesst) ) + { // Ouch! Very very bad! + LOG(0, 0, 0, "DANGER: Received a C_CGROUPE that didn't decompress correctly!\n"); + // Now what? Should exit! No-longer up to date! + break; + } + + cluster_recv_groupe(more, c); + break; + } + case C_GROUPE: + if ( s < sizeof(grpsession[more])) + goto shortpacket; + + cluster_recv_groupe(more, p); + + p += sizeof(grpsession[more]); + s -= sizeof(grpsession[more]); + break; + default: LOG(0, 0, 0, "DANGER: I received a heartbeat element where I didn't understand the type! (%d)\n", type); return -1; // can't process any more of the packet!! @@@ -2098,7 -1954,7 +2098,7 @@@ shortpacket //==================================================================================================== - int cmd_show_cluster(struct cli_def *cli, char *command, char **argv, int argc) + int cmd_show_cluster(struct cli_def *cli, const char *command, char **argv, int argc) { int i; @@@ -2122,14 -1978,12 +2122,14 @@@ cli_print(cli, "Next sequence number expected: %d", config->cluster_seq_number); cli_print(cli, "%d sessions undefined of %d", config->cluster_undefined_sessions, config->cluster_highest_sessionid); cli_print(cli, "%d bundles undefined of %d", config->cluster_undefined_bundles, config->cluster_highest_bundleid); + cli_print(cli, "%d groupes undefined of %d", config->cluster_undefined_groupes, config->cluster_highest_groupeid); cli_print(cli, "%d tunnels undefined of %d", config->cluster_undefined_tunnels, config->cluster_highest_tunnelid); } else { cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version); cli_print(cli, "Next heartbeat # : %d", config->cluster_seq_number); cli_print(cli, "Highest session : %d", config->cluster_highest_sessionid); cli_print(cli, "Highest bundle : %d", config->cluster_highest_bundleid); + cli_print(cli, "Highest groupe : %d", config->cluster_highest_groupeid); cli_print(cli, "Highest tunnel : %d", config->cluster_highest_tunnelid); cli_print(cli, "%d changes queued for sending", config->cluster_num_changes); } diff --combined cluster.h index 794cc9d,bb7ca5a..b1aebaf --- a/cluster.h +++ b/cluster.h @@@ -25,9 -25,6 +25,9 @@@ #define C_CBUNDLE 18 // Compressed bundle structure. #define C_MPPP_FORWARD 19 // MPPP Forwarded packet.. #define C_PPPOE_FORWARD 20 // PPPOE Forwarded packet.. +#define C_GROUPE 21 // Groupe structure. +#define C_CGROUPE 22 // Compressed groupe structure. + #define HB_VERSION 7 // Protocol version number.. #define HB_MAX_SEQ (1<<30) // Maximum sequence number. (MUST BE A POWER OF 2!) @@@ -61,10 -58,7 +61,10 @@@ typedef struct uint64_t table_version; // # state changes processed by cluster - char reserved[128 - 13*sizeof(uint32_t) - sizeof(uint64_t)]; // Pad out to 128 bytes. + uint32_t highgroupe; // Id of the highest used groupe. + uint32_t nextgrpid; // nextgrpid to set gnextgrpid on slave + + char reserved[128 - 15*sizeof(uint32_t) - sizeof(uint64_t)]; // Pad out to 128 bytes. } heartt; typedef struct { /* Used to update byte counters on the */ @@@ -87,7 -81,6 +87,7 @@@ int cluster_init(void) int processcluster(uint8_t *buf, int size, in_addr_t addr); int cluster_send_session(int sid); int cluster_send_bundle(int bid); +int cluster_send_groupe(int gid); int cluster_send_tunnel(int tid); int master_forward_packet(uint8_t *data, int size, in_addr_t addr, uint16_t port, uint16_t indexudp); int master_forward_dae_packet(uint8_t *data, int size, in_addr_t addr, int port); @@@ -99,7 -92,7 +99,7 @@@ void cluster_send_ping(time_t basetime) void cluster_heartbeat(void); void cluster_check_master(void); void cluster_check_slaves(void); - int cmd_show_cluster(struct cli_def *cli, char *command, char **argv, int argc); + int cmd_show_cluster(struct cli_def *cli, const char *command, char **argv, int argc); int master_forward_pppoe_packet(uint8_t *data, int size, uint8_t codepad); #endif /* __CLUSTER_H__ */ diff --combined debian/changelog index 07531e8,8600178..61a117a --- a/debian/changelog +++ b/debian/changelog @@@ -1,49 -1,54 +1,67 @@@ -l2tpns (2.2.1-2fdn3.11) UNRELEASED; urgency=low ++l2tpns (2.2.1-2sames3.12) UNRELEASED; urgency=low + + * Fix: throttle ipv6 out. + * Fix: remove old IPV6 routes on slave + * Fix: compiling Warning, dpkg-buildflags ... + * Enabled hardened build flags, thanks Moritz Muehlenhoff (closes: #657846) + * Packaging updates + * Move to 3.0 (native) source format + * Bump DH compat level to 8 + * Fix ordering of stdio.h/syslog.h includes (closes: #707385) + * Create accounting_dir in init script if necessary (closes: #418156) + * Bump Standards-Version to 3.9.4.0 + * Add build-arch/build-indep targets to debian/rules + * Fix: compiling Warning ++ * improved load balancing algorithm. + - -- Fernando Alves Sun, 06 Oct 2013 10:38:53 +0200 ++ -- Fernando Alves Sun, 07 Oct 2013 22:20:53 +0200 + -l2tpns (2.2.1-2fdn3.10) unstable; urgency=low +l2tpns (2.2.1-2sames3.11) unstable; urgency=low + + * improved load balancing algorithm. + + -- Fernando Alves Fri, 02 Aug 2013 11:32:49 +0200 + +l2tpns (2.2.1-2sames3.10) unstable; urgency=low * Fix: authentication success was sent 2 times. + * Fix: session mismatch on group. - -- Fernando Alves Tue, 04 Jun 2013 11:38:04 +0200 + -- Fernando Alves Tue, 04 Jun 2013 14:36:37 +0200 -l2tpns (2.2.1-2fdn3.9) unstable; urgency=low +l2tpns (2.2.1-2sames3.9) unstable; urgency=low * Adding the possibility to set multiple hostname. - -- Fernando Alves Thu, 23 May 2013 23:58:23 +0200 + -- Fernando Alves Wed, 22 May 2013 22:25:59 +0200 -l2tpns (2.2.1-2fdn3.8) unstable; urgency=low +l2tpns (2.2.1-2sames3.8) unstable; urgency=low - * Fix: send SCCCN requested challenge response. + * Fix send SCCCN requested challenge response. * add accounting parameter account_all_origin. * Fix service_name management and add pppoe_only_equal_svc_name parameter. + * Fix cluster group update. + * Fix possible IPv6 spoofing. + * manage groupes in cluster mode. + * Adding the possibility to listening multiple IP L2TP tunnels. + * Add cli show group and update rate calculation. - -- Fernando Alves Tue, 30 Apr 2013 16:02:33 +0200 - -l2tpns (2.2.1-2fdn3.7) unstable; urgency=low - - * Adding the possibility to listening multiple IP L2TP Tunnels - * Removing LAC flag. + -- Fernando Alves Tue, 30 Apr 2013 19:22:11 +0200 - -- Fernando Alves Thu, 28 Mar 2013 10:50:00 +0100 - -l2tpns (2.2.1-2fdn3.6) unstable; urgency=low +l2tpns (2.2.1-2sames3.7) unstable; urgency=low + * Merge from master * Fix Warning: dereferencing type-punned pointer will break strict... * Fix: Tunnel creation does not work when the length of the hostname is odd. (revert fix: Add a uint16_t control buffer type, as a union) -- Fernando Alves Tue, 26 Feb 2013 09:07:16 +0100 +l2tpns (2.2.1-2sames3.6) unstable; urgency=low + + * Sames l2tpns version. + + -- Fernando Alves Tue, 12 Feb 2013 20:20:17 +0100 + l2tpns (2.2.1-2fdn3.5) unstable; urgency=low * Update debian/changelog diff --combined garden.c index 63135ea,0795196..863114e --- a/garden.c +++ b/garden.c @@@ -3,9 -3,6 +3,9 @@@ #include #include #include +#include +#include + #include "l2tpns.h" #include "plugin.h" #include "control.h" @@@ -160,7 -157,7 +160,7 @@@ int plugin_become_master(void for (i = 0; up_commands[i] && *up_commands[i]; i++) { f->log(3, 0, 0, "Running %s\n", up_commands[i]); - system(up_commands[i]); + if (-1 == system(up_commands[i])) f->log(0, 0, 0, "error command %s\n", up_commands[i]); } return PLUGIN_RET_OK; @@@ -179,6 -176,7 +179,7 @@@ int garden_session(sessiont *s, int fla { char cmd[2048]; sessionidt sess; + int status; if (!s) return 0; if (!s->opened) return 0; @@@ -194,7 -192,7 +195,7 @@@ f->fmtaddr(htonl(s->ip), 0)); f->log(3, sess, s->tunnel, "%s\n", cmd); - system(cmd); + status = system(cmd); s->walled_garden = 1; } else @@@ -232,7 -230,7 +233,7 @@@ f->log(3, sess, s->tunnel, "%s\n", cmd); while (--count) { - int status = system(cmd); + status = system(cmd); if (WEXITSTATUS(status) != 0) break; } @@@ -275,7 -273,7 +276,7 @@@ int plugin_init(struct pluginfuncs *fun for (i = 0; down_commands[i] && *down_commands[i]; i++) { f->log(3, 0, 0, "Running %s\n", down_commands[i]); - system(down_commands[i]); + if (-1 == system(down_commands[i])) f->log(0, 0, 0, "error command %s\n", down_commands[i]); } } @@@ -292,7 -290,7 +293,7 @@@ void plugin_done( for (i = 0; down_commands[i] && *down_commands[i]; i++) { f->log(3, 0, 0, "Running %s\n", down_commands[i]); - system(down_commands[i]); + if (-1 == system(down_commands[i])) f->log(0, 0, 0, "error command %s\n", down_commands[i]); } } diff --combined grpsess.c index ccaa27c,0000000..d3fae30 mode 100644,000000..100644 --- a/grpsess.c +++ b/grpsess.c @@@ -1,709 -1,0 +1,709 @@@ +/* + * Fernando ALVES 2013 + * Grouped session for load balancing and fail-over + * GPL licenced + */ + +#include +#include +#include +#include +#include + +#include "l2tpns.h" +#include "util.h" +#include "cluster.h" + +#ifdef BGP +#include "bgp.h" +#endif + +union grp_iphash { + groupidt grp; + union grp_iphash *idx; +} grp_ip_hash[256]; // Mapping from IP address to group structures. + +groupidt gnextgrpid = 0; + +typedef struct +{ + sessionidt sid_loaddist[0x10000]; +} +local_group; + +local_group *grp_local = NULL; // Array of local_group structures. + +// Find gruop by IP, < 1 for not found +// +// Confusingly enough, this 'ip' must be +// in _network_ order. This being the common +// case when looking it up from IP packet headers. +static groupidt grp_lookup_ipmap(in_addr_t ip) +{ + uint8_t *a = (uint8_t *) &ip; + union grp_iphash *h = grp_ip_hash; + + if (!(h = h[*a++].idx)) return 0; + if (!(h = h[*a++].idx)) return 0; + if (!(h = h[*a++].idx)) return 0; + + return h[*a].grp; +} + +// +// Take an IP address in HOST byte order and +// add it to the grouid by IP cache. +// +// (It's actually cached in network order) +// +static void grp_cache_ipmap(in_addr_t ip, groupidt g) +{ + in_addr_t nip = htonl(ip); // MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0] + uint8_t *a = (uint8_t *) &nip; + union grp_iphash *h = grp_ip_hash; + int i; + + for (i = 0; i < 3; i++) + { + if (!(h[a[i]].idx || (h[a[i]].idx = calloc(256, sizeof(union grp_iphash))))) + return; + + h = h[a[i]].idx; + } + + h[a[3]].grp = g; + + if (g > 0) + LOG(4, 0, 0, "Caching Group:%d ip address %s\n", g, fmtaddr(nip, 0)); + else if (g == 0) + LOG(4, 0, 0, "Un-caching Group ip address %s\n", fmtaddr(nip, 0)); +} + +groupidt grp_groupbyip(in_addr_t ip) +{ + groupidt g = grp_lookup_ipmap(ip); + + if (g > 0 && g < MAXGROUPE) + return g; + + return 0; +} + +// Add a route +// +// This adds it to the routing table, advertises it +// via BGP if enabled, and stuffs it into the +// 'groupbyip' cache. +// +// 'ip' must be in _host_ order. +// +static void grp_routeset(groupidt g, in_addr_t ip, int prefixlen, int add) +{ + struct { + struct nlmsghdr nh; + struct rtmsg rt; + char buf[32]; + } req; + int i; + in_addr_t n_ip; + + if (!prefixlen) prefixlen = 32; + + ip &= 0xffffffff << (32 - prefixlen);; // Force the ip to be the first one in the route. + + memset(&req, 0, sizeof(req)); + + if (add) + { + req.nh.nlmsg_type = RTM_NEWROUTE; + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE; + } + else + { + req.nh.nlmsg_type = RTM_DELROUTE; + req.nh.nlmsg_flags = NLM_F_REQUEST; + } + + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt)); + + req.rt.rtm_family = AF_INET; + req.rt.rtm_dst_len = prefixlen; + req.rt.rtm_table = RT_TABLE_MAIN; + req.rt.rtm_protocol = 42; + req.rt.rtm_scope = RT_SCOPE_LINK; + req.rt.rtm_type = RTN_UNICAST; + + netlink_addattr(&req.nh, RTA_OIF, &tunidx, sizeof(int)); + n_ip = htonl(ip); + netlink_addattr(&req.nh, RTA_DST, &n_ip, sizeof(n_ip)); + + LOG(3, 0, 0, "Route (Group) %s %s/%d\n", add ? "add" : "del", fmtaddr(htonl(ip), 0), prefixlen); + + if (netlink_send(&req.nh) < 0) + LOG(0, 0, 0, "grp_routeset() error in sending netlink message: %s\n", strerror(errno)); + +#ifdef BGP + if (add) + bgp_add_route(htonl(ip), prefixlen); + else + bgp_del_route(htonl(ip), prefixlen); +#endif /* BGP */ + + // Add/Remove the IPs to the 'groupbyip' cache. + // Note that we add the zero address in the case of + // a network route. Roll on CIDR. + + // Note that 'g == 0' implies this is the address pool. + // We still cache it here, because it will pre-fill + // the malloc'ed tree. + if (g) + { + if (!add) // Are we deleting a route? + g = 0; // Caching the session as '0' is the same as uncaching. + + for (i = ip; i < ip+(1<<(32-prefixlen)) ; ++i) + { + grp_cache_ipmap(i, g); + if (!g) cache_ipmap(i, 0); + } + } +} + +// Set all route of a group +void grp_setgrouproute(groupidt g, int add) +{ + int i; + for (i = 0; i < grpsession[g].nbroutesgrp; i++) + { + if (grpsession[g].route[i].ip != 0) + { + grp_routeset(g, grpsession[g].route[i].ip, grpsession[g].route[i].prefixlen, add); + } + } +} + +// return group id by session +groupidt grp_groupbysession(sessionidt s) +{ + groupidt g = 0; + int i; + for (g = gnextgrpid; g != 0; g = grpsession[g].prev) + { + for (i = 0; i < grpsession[g].nbsession; i++) + { + if (grpsession[g].sesslist[i].sid == s) + { // session found in group + return g; + } + } + } + + return 0; +} + +// Remove a session to a group +// return 1 if OK +void grp_removesession(groupidt g, sessionidt s) +{ + int i; + + if (grpsession[g].nbsession <= 0) + return; + + for (i = 0; i < grpsession[g].nbsession; i++) + { + if (grpsession[g].sesslist[i].sid == s) + { // session found on group + --grpsession[g].nbsession; + if (grpsession[g].nbsession == 0) + { + // Group is empty, remove it + + // Del all routes + grp_setgrouproute(g, 0); + + if (gnextgrpid == g) + { + gnextgrpid = grpsession[g].prev; + } + else + { + groupidt g2; + for (g2 = gnextgrpid; g2 != 0; g2 = grpsession[g2].prev) + { + if (grpsession[g2].prev == g) + { + grpsession[g2].prev = grpsession[g].prev; + break; + } + } + } + + memset(&grpsession[g], 0, sizeof(grpsession[0])); + grpsession[g].state = GROUPEFREE; + } + else + { + // remove the session + memmove(&grpsession[g].sesslist[i], + &grpsession[g].sesslist[i+1], + (grpsession[g].nbsession - i) * sizeof(grpsession[g].sesslist[i])); + } + + cluster_send_groupe(g); + return; + } + } +} + +// Add a session to a group +// return 1 if OK +static int grp_addsession(groupidt g, sessionidt s, uint8_t weight) +{ + int i; + + for (i = 0; i < grpsession[g].nbsession; i++) + { + if (grpsession[g].sesslist[i].sid == s) + { // already in group + if ((!grpsession[g].sesslist[i].weight) || (weight > 1)) + grpsession[g].sesslist[i].weight = weight; // update Weight session (for load-balancing) + + return 1; + } + } + + if (i >= MAXSESSINGRP) + { + LOG(1, s, session[s].tunnel, " Too many session for Group %d\n", g); + return 0; + } + else + { // add session id to group + if (i == 0) + { + // it's the first session of the group, set to next group + grpsession[g].prev = gnextgrpid; + gnextgrpid = g; + grpsession[g].state = GROUPEOPEN; + } + grpsession[g].sesslist[i].sid = s; + grpsession[g].sesslist[i].weight = weight; + grpsession[g].nbsession++; + + return 1; + } + return 0; +} + +// Add a route to a group +// return 1 if OK +static int grp_addroute(groupidt g, sessionidt s, in_addr_t ip, int prefixlen) +{ + int i; + + for (i = 0; i < MAXROUTEINGRP; i++) + { + if ((i >= grpsession[g].nbroutesgrp)) + { + LOG(3, s, session[s].tunnel, " Radius reply Group %d contains route for %s/%d\n", + g, fmtaddr(htonl(ip), 0), prefixlen); + + grpsession[g].route[i].ip = ip; + grpsession[g].route[i].prefixlen = prefixlen; + grpsession[g].nbroutesgrp++; + return 1; + } + else if ((grpsession[g].route[i].ip == ip) && (grpsession[g].route[i].prefixlen == prefixlen)) + { + // route already defined in group + LOG(3, s, session[s].tunnel, + " Radius reply Group %d contains route for %s/%d (this already defined)\n", + g, fmtaddr(htonl(ip), 0), prefixlen); + + return 1; + } + else if (grpsession[g].route[i].ip == 0) + { + LOG(3, s, session[s].tunnel, " Radius reply Group %d contains route for %s/%d (find empty on list!!!)\n", + g, fmtaddr(htonl(ip), 0), prefixlen); + + grpsession[g].route[i].ip = ip; + grpsession[g].route[i].prefixlen = prefixlen; + return 1; + } + } + + if (i >= MAXROUTEINGRP) + { + LOG(1, s, session[s].tunnel, " Too many routes for Group %d\n", g); + } + return 0; +} + +// Process Sames vendor specific attribut radius +void grp_processvendorspecific(sessionidt s, uint8_t *pvs) +{ + uint8_t attrib = *pvs; + groupidt grpid = 0; + uint8_t *n = pvs + 2; + uint8_t *e = pvs + pvs[1]; + + if ((attrib >= 22) && (attrib <= 23)) + { + while (n < e && isdigit(*n)) + { + grpid = grpid * 10 + *n - '0'; + n++; + } + if ((grpid == 0) || (grpid >= MAXGROUPE)) + { + LOG(1, s, session[s].tunnel, " Group Attribute Id %d not allowed\n", grpid); + return; + } + else if (*n != ',') + { + LOG(1, s, session[s].tunnel, " Group Attribute Id not defined\n"); + return; + } + + if (!grp_addsession(grpid, s, 1)) + { + return; + } + + if (grpid > config->cluster_highest_groupeid) + config->cluster_highest_groupeid = grpid; + + n++; + } + + //process, Sames vendor-specific 64520 + if (attrib == 22) //SAMES-Group-Framed-Route + { + in_addr_t ip = 0; + uint8_t u = 0; + uint8_t bits = 0; + + while (n < e && (isdigit(*n) || *n == '.')) + { + if (*n == '.') + { + ip = (ip << 8) + u; + u = 0; + } + else + u = u * 10 + *n - '0'; + n++; + } + ip = (ip << 8) + u; + if (*n == '/') + { + n++; + while (n < e && isdigit(*n)) + bits = bits * 10 + *n++ - '0'; + } + else if ((ip >> 24) < 128) + bits = 8; + else if ((ip >> 24) < 192) + bits = 16; + else + bits = 24; + + if (!grp_addroute(grpid, s, ip, bits)) + return; + } + else if (attrib == 23) //SAMES-Group-Session-Weight + { + uint8_t weight = 0; + + while (n < e && isdigit(*n)) + weight = weight * 10 + *n++ - '0'; + + if (!weight) + { + LOG(1, s, session[s].tunnel, " Group-Session-Weight 0 GroupId %d not allowed\n", grpid); + return; + } + if (!grp_addsession(grpid, s, weight)) + { + return; + } + } + else + { + LOG(3, s, session[s].tunnel, " Unknown vendor-specific: 64520, Attrib: %d\n", attrib); + } +} + +// Init data structures +void grp_initdata() +{ + int i; + + // Set default value (10s) + config->grp_txrate_average_time = 10; + + if (!(grpsession = shared_malloc(sizeof(groupsesst) * MAXGROUPE))) + { + LOG(0, 0, 0, "Error doing malloc for grouped session: %s\n", strerror(errno)); + exit(1); + } + + memset(grpsession, 0, sizeof(grpsession[0]) * MAXGROUPE); + for (i = 1; i < MAXGROUPE; i++) + { + grpsession[i].state = GROUPEUNDEF; + } + + if (!(grp_local = shared_malloc(sizeof(local_group) * MAXGROUPE))) + { + LOG(0, 0, 0, "Error doing malloc for grp_local: %s\n", strerror(errno)); + exit(1); + } + memset(grp_local, 0, sizeof(grp_local[0]) * MAXGROUPE); + +} + +// Update time_changed of the group +void grp_time_changed() +{ + groupidt g; + + for (g = gnextgrpid; g != 0; g = grpsession[g].prev) + { + grpsession[g].time_changed++; + } +} + +// Uncache all IP of a session +static void grp_uncache_ipsession(groupidt g, sessionidt s) +{ + int i; + uint8_t *a; + in_addr_t ip; + in_addr_t n_ip, j; + int prefixlen; + union iphash *h; + + for (i = 0; i < grpsession[g].nbroutesgrp; i++) + { + if (grpsession[g].route[i].ip != 0) + { + prefixlen = grpsession[g].route[i].prefixlen; + ip = grpsession[g].route[i].ip & (0xffffffff << (32 - prefixlen)); // Force the ip to be the first one in the route. + + for (j = ip; j < ip+(1<<(32-prefixlen)) ; ++j) + { + n_ip = htonl(j); // To network order + a = (uint8_t *) &n_ip; + h = ip_hash; + + if (!(h = h[*a++].idx)) continue; + if (!(h = h[*a++].idx)) continue; + if (!(h = h[*a++].idx)) continue; + + if (s == h[*a].sess) + { + h[*a].sess = 0; + //LOG(3, s, session[s].tunnel, "UnCaching ip address %s\n", fmtaddr(n_ip, 0)); + } + } + } + } +} + +uint16_t guint16_index_loadlist; +// return the next session can be used on the group +sessionidt grp_getnextsession(groupidt g, in_addr_t ip, in_addr_t ip_src) +{ + sessionidt s = 0, s2 = 0, s3 = 0; + int i; + uint32_t ltime_changed = 0, mintxrate = 0xFFFFFFFF, maxtxrate = 0; - uint32_t txrate; ++ uint32_t txrate = 0; + + if (g >= MAXGROUPE) + return 0; + + if (grpsession[g].time_changed >= config->grp_txrate_average_time) + { + // recalculation txrate + ltime_changed = grpsession[g].time_changed; + grpsession[g].time_changed = 0; + for (i = 0; i < grpsession[g].nbsession; i++) + { + if ((s2 = grpsession[g].sesslist[i].sid)) + { + uint32_t coutgrp_delta = 0; + + if (session[s2].cout >= grpsession[g].sesslist[i].prev_coutgrp) + coutgrp_delta = session[s2].cout - grpsession[g].sesslist[i].prev_coutgrp; + grpsession[g].sesslist[i].prev_coutgrp = session[s2].cout; + + txrate = (txrate + (coutgrp_delta/ltime_changed)) >> 1; + grpsession[g].sesslist[i].tx_rate = txrate; + + txrate = grpsession[g].sesslist[i].tx_rate/grpsession[g].sesslist[i].weight; + if (txrate < mintxrate) + { + if ( session[s2].ppp.phase > Establish && + (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) ) + { + grpsession[g].smin = s2; + mintxrate = txrate; + } + } + + if (txrate > maxtxrate) + { + if ( session[s2].ppp.phase > Establish && + (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) ) + { + grpsession[g].smax = s2; + maxtxrate = txrate; + } + } + } + } + } + + if ((s = sessionbyip(ip))) + { + uint8_t *as = (uint8_t *) &ip_src; + uint8_t *ad = (uint8_t *) &ip; + uint16_t ai = ad[3]; + ai <<= 8; + ai |= as[3]; + + s = grp_local[g].sid_loaddist[ai]; + if (!s) + { + s = grpsession[g].smin; + grp_local[g].sid_loaddist[ai] = s; + } + + if (g != grp_groupbysession(s)) + { + // This session does not belong to this group + LOG(3, s, session[s].tunnel, "Warning, the session does not belong to group %d\n", g); + s = 0; + grp_local[g].sid_loaddist[ai] = 0; + } + else if ( (session[s].ppp.phase > Establish) && + (time_now - session[s].last_packet <= (config->echo_timeout + 1)) ) + { + grp_local[g].sid_loaddist[guint16_index_loadlist++] = 0; + return s; + } + else + { + s = 0; + grp_local[g].sid_loaddist[ai] = 0; + } + } + + if (!s) + { + // random between 0 and nbsession-1 + uint indexsess = (rand() % grpsession[g].nbsession); + + if (indexsess >= grpsession[g].nbsession) + indexsess = 0; //Sanity checks. + + s2 = grpsession[g].sesslist[indexsess].sid; + if (s2 && + (session[s2].ppp.phase > Establish) && + (time_now - session[s2].last_packet <= (config->echo_timeout + 1))) + { + s = s2; + } + else + { + for (i = 0; i < grpsession[g].nbsession; i++) + { + if ((s2 = grpsession[g].sesslist[i].sid)) + { + s3 = s2; + + if ( session[s2].ppp.phase > Establish && + (time_now - session[s2].last_packet <= (config->echo_timeout + 1)) ) + { + s = s2; + break; + } + } + } + } + } + + if (!s) + s = s3; + + if (s) + cache_ipmap(ntohl(ip), s); + + return s; +} + +// load a groupe receive from master +int grp_cluster_load_groupe(groupidt g, groupsesst *new) +{ + int i; + int updategroup = 0; + + if (g >= MAXGROUPE) + { + LOG(0, 0, 0, "ERROR: Received a group id > MAXGROUPE!\n"); + return 0; + } + + if ((grpsession[g].nbroutesgrp != new->nbroutesgrp) || + (grpsession[g].nbsession != new->nbsession)) + { + updategroup = 1; + } + + if (!updategroup) + { + // Check session list + for (i = 0; i < grpsession[g].nbsession; i++) + { + if (grpsession[g].sesslist[i].sid != new->sesslist[i].sid) + { + updategroup = 1; + break; + } + } + } + + if (!updategroup) + { + // Check routes list + for (i = 0; i < grpsession[g].nbroutesgrp; i++) + { + if (grpsession[g].route[i].ip != new->route[i].ip) + { + updategroup = 1; + break; + } + } + } + + // needs update + if (updategroup) + { + // Del all routes + grp_setgrouproute(g, 0); + } + + memcpy(&grpsession[g], new, sizeof(grpsession[g])); // Copy over.. + + // needs update + if (updategroup) + { + // Add all routes + grp_setgrouproute(g, 1); + } + + return 1; +} diff --combined l2tpns.c index 9861e88,4028379..867730b --- a/l2tpns.c +++ b/l2tpns.c @@@ -10,6 -10,7 +10,7 @@@ #include #include #define SYSLOG_NAMES + #include #include #include #include @@@ -19,7 -20,6 +20,6 @@@ #include #include #include - #include #include #include #include @@@ -75,7 -75,7 +75,7 @@@ int cluster_sockfd = -1; // Intra-clust int epollfd = -1; // event polling time_t basetime = 0; // base clock char hostname[MAXHOSTNAME] = ""; // us. -static int tunidx; // ifr_ifindex of tun device +int tunidx; // ifr_ifindex of tun device int nlseqnum = 0; // netlink sequence number int min_initok_nlseqnum = 0; // minimun seq number for messages after init is ok static int syslog_log = 0; // are we logging to syslog @@@ -92,7 -92,10 +92,7 @@@ uint16_t MSS = 0; // TCP MS struct cli_session_actions *cli_session_actions = NULL; // Pending session changes requested by CLI struct cli_tunnel_actions *cli_tunnel_actions = NULL; // Pending tunnel changes required by CLI -union iphash { - sessionidt sess; - union iphash *idx; -} ip_hash[256]; // Mapping from IP address to session structures. +union iphash ip_hash[256]; // Mapping from IP address to session structures. struct ipv6radix { sessionidt sess; @@@ -183,7 -186,6 +183,7 @@@ config_descriptt config_values[] = CONFIG("disable_sending_hello", disable_sending_hello, BOOL), CONFIG("disable_no_spoof", disable_no_spoof, BOOL), CONFIG("bind_multi_address", bind_multi_address, STRING), + CONFIG("grp_txrate_average_time", grp_txrate_average_time, INT), CONFIG("pppoe_only_equal_svc_name", pppoe_only_equal_svc_name, BOOL), CONFIG("multi_hostname", multi_hostname, STRING), { NULL, 0, 0, 0 } @@@ -214,7 -216,6 +214,7 @@@ tunnelt *tunnel = NULL; // Array of t bundlet *bundle = NULL; // Array of bundle structures. fragmentationt *frag = NULL; // Array of fragmentation structures. sessiont *session = NULL; // Array of session structures. +groupsesst *grpsession = NULL; // Array of groupsesst structures. sessionlocalt *sess_local = NULL; // Array of local per-session counters. radiust *radius = NULL; // Array of radius structures. ippoolt *ip_address_pool = NULL; // Array of dynamic IP addresses. @@@ -225,6 -226,9 +225,6 @@@ struct Tstats *_statistics = NULL struct Tringbuffer *ringbuffer = NULL; #endif -static ssize_t netlink_send(struct nlmsghdr *nh); -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen); -static void cache_ipmap(in_addr_t ip, sessionidt s); static void uncache_ipmap(in_addr_t ip); static void cache_ipv6map(struct in6_addr ip, int prefixlen, sessionidt s); static void free_ip_address(sessionidt s); @@@ -253,9 -257,8 +253,9 @@@ static clockt now(double *f if (f) *f = t.tv_sec + t.tv_usec / 1000000.0; if (t.tv_sec != time_now) { - time_now = t.tv_sec; - time_changed++; + time_now = t.tv_sec; + time_changed++; + grp_time_changed(); } // Time in milliseconds @@@ -614,7 -617,7 +614,7 @@@ static void initnetlink(void } } -static ssize_t netlink_send(struct nlmsghdr *nh) +ssize_t netlink_send(struct nlmsghdr *nh) { struct sockaddr_nl nladdr; struct iovec iov; @@@ -650,7 -653,7 +650,7 @@@ static ssize_t netlink_recv(void *buf, } /* adapted from iproute2 */ -static void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; @@@ -1010,8 -1013,10 +1010,10 @@@ sessionidt sessionbyipv6(struct in6_add ip.s6_addr[1] == 0x80 && ip.s6_addr16[1] == 0 && ip.s6_addr16[2] == 0 && - ip.s6_addr16[3] == 0)) { - s = lookup_ipmap(*(in_addr_t *) &ip.s6_addr[8]); + ip.s6_addr16[3] == 0)) + { + in_addr_t *pipv4 = (in_addr_t *) &ip.s6_addr[8]; + s = lookup_ipmap(*pipv4); } else { s = lookup_ipv6map(ip); } @@@ -1028,7 -1033,7 +1030,7 @@@ // // (It's actually cached in network order) // -static void cache_ipmap(in_addr_t ip, sessionidt s) +void cache_ipmap(in_addr_t ip, sessionidt s) { in_addr_t nip = htonl(ip); // MUST be in network order. I.e. MSB must in be ((char *) (&ip))[0] uint8_t *a = (uint8_t *) &nip; @@@ -1097,7 -1102,7 +1099,7 @@@ static void cache_ipv6map(struct in6_ad // // CLI list to dump current ipcache. // - int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc) + int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int argc) { union iphash *d = ip_hash, *e, *f, *g; int i, j, k, l; @@@ -1410,10 -1415,9 +1412,10 @@@ static void update_session_out_stat(ses void processipout(uint8_t *buf, int len) { sessionidt s; + groupidt g; sessiont *sp; tunnelidt t; - in_addr_t ip; + in_addr_t ip, ip_src; uint8_t *data = buf; // Keep a copy of the originals. int size = len; @@@ -1446,33 -1450,8 +1448,33 @@@ return; } + ip_src = *(uint32_t *)(buf + 12); ip = *(uint32_t *)(buf + 16); - if (!(s = sessionbyip(ip))) + if ((g = grp_groupbyip(ip))) + { + s = grp_getnextsession(g, ip, ip_src); + if (!s) + { + // Is this a packet for a session that doesn't exist? + static int rate = 0; // Number of ICMP packets we've sent this second. + static int last = 0; // Last time we reset the ICMP packet counter 'rate'. + + if (last != time_now) + { + last = time_now; + rate = 0; + } + + if (rate++ < config->icmp_rate) // Only send a max of icmp_rate per second. + { + LOG(4, 0, 0, "IP: Sending ICMP host unreachable to %s\n", fmtaddr(*(in_addr_t *)(buf + 12), 0)); + host_unreachable(*(in_addr_t *)(buf + 12), *(uint16_t *)(buf + 4), + config->bind_address ? config->bind_address : my_address, buf, len); + } + return; + } + } + else if (!(s = sessionbyip(ip))) { // Is this a packet for a session that doesn't exist? static int rate = 0; // Number of ICMP packets we've sent this second. @@@ -1822,6 -1801,8 +1824,8 @@@ static void send_ipout(sessionidt s, ui { sessiont *sp; tunnelidt t; + uint8_t *p; + uint8_t *data = buf; // Keep a copy of the originals. uint8_t b[MAXETHER + 20]; @@@ -1844,11 -1825,14 +1848,14 @@@ LOG(5, s, t, "Ethernet -> Tunnel (%d bytes)\n", len); // Add on L2TP header - { - uint8_t *p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); - if (!p) return; - tunnelsend(b, len + (p-b), t); // send it... - } + if (*(uint16_t *) (data + 2) == htons(PKTIPV6)) + p = makeppp(b, sizeof(b), buf, len, s, t, PPPIPV6, 0, 0, 0); // IPV6 + else + p = makeppp(b, sizeof(b), buf, len, s, t, PPPIP, 0, 0, 0); // IPV4 + + if (!p) return; + + tunnelsend(b, len + (p-b), t); // send it... // Snooping this session. if (sp->snoop_ip && sp->snoop_port) @@@ -1867,10 -1851,11 +1874,11 @@@ static void control16(controlt * c, uint16_t avp, uint16_t val, uint8_t m) { uint16_t l = (m ? 0x8008 : 0x0008); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint16_t *) (c->buf + c->length + 6) = htons(val); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); + pint16[3] = htons(val); c->length += 8; } @@@ -1878,10 -1863,12 +1886,12 @@@ static void control32(controlt * c, uint16_t avp, uint32_t val, uint8_t m) { uint16_t l = (m ? 0x800A : 0x000A); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); - *(uint32_t *) (c->buf + c->length + 6) = htonl(val); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + uint32_t *pint32 = (uint32_t *) (c->buf + c->length + 6); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); + pint32[0] = htonl(val); c->length += 10; } @@@ -1889,9 -1876,10 +1899,10 @@@ static void controls(controlt * c, uint16_t avp, char *val, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + strlen(val) + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); memcpy(c->buf + c->length + 6, val, strlen(val)); c->length += 6 + strlen(val); } @@@ -1900,9 -1888,10 +1911,10 @@@ static void controlb(controlt * c, uint16_t avp, uint8_t *val, unsigned int len, uint8_t m) { uint16_t l = ((m ? 0x8000 : 0) + len + 6); - *(uint16_t *) (c->buf + c->length + 0) = htons(l); - *(uint16_t *) (c->buf + c->length + 2) = htons(0); - *(uint16_t *) (c->buf + c->length + 4) = htons(avp); + uint16_t *pint16 = (uint16_t *) (c->buf + c->length + 0); + pint16[0] = htons(l); + pint16[1] = htons(0); + pint16[2] = htons(avp); memcpy(c->buf + c->length + 6, val, len); c->length += 6 + len; } @@@ -1947,10 -1936,11 +1959,11 @@@ static void controlnull(tunnelidt t // add a control message to a tunnel, and send if within window static void controladd(controlt *c, sessionidt far, tunnelidt t) { - *(uint16_t *) (c->buf + 2) = htons(c->length); // length - *(uint16_t *) (c->buf + 4) = htons(tunnel[t].far); // tunnel - *(uint16_t *) (c->buf + 6) = htons(far); // session - *(uint16_t *) (c->buf + 8) = htons(tunnel[t].ns); // sequence + uint16_t *pint16 = (uint16_t *) (c->buf + 2); + pint16[0] = htons(c->length); // length + pint16[1] = htons(tunnel[t].far); // tunnel + pint16[2] = htons(far); // session + pint16[3] = htons(tunnel[t].ns); // sequence tunnel[t].ns++; // advance sequence // link in message in to queue if (tunnel[t].controlc) @@@ -2103,7 -2093,7 +2116,7 @@@ void sessionshutdown(sessionidt s, cha session[s].die = TIME + 150; // Clean up in 15 seconds if (session[s].ip) - { // IP allocated, clear and unroute + { // IP allocated, clear and unroute int r; int routed = 0; for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@@ -2303,8 -2293,6 +2316,8 @@@ static void sessionclear(sessionidt s // kill a session now void sessionkill(sessionidt s, char *reason) { + groupidt g; + CSTAT(sessionkill); if (!session[s].opened) // not alive @@@ -2333,12 -2321,6 +2346,12 @@@ } LOG(2, s, session[s].tunnel, "Kill session %d (%s): %s\n", s, session[s].user, reason); + + if ((g = grp_groupbysession(s))) + { + grp_removesession(g, s); + } + sessionclear(s); cluster_send_session(s); } @@@ -3736,7 -3718,7 +3749,7 @@@ static void regular_cleanups(double per // No data in ECHO_TIMEOUT seconds, send LCP ECHO if (session[s].ppp.phase >= Establish && (time_now - session[s].last_packet >= config->echo_timeout) && - (time_now - sess_local[s].last_echo >= ECHO_TIMEOUT)) + (time_now - sess_local[s].last_echo >= config->echo_timeout)) { uint8_t b[MAXETHER]; @@@ -4673,8 -4655,6 +4686,8 @@@ static void initdata(int optdebug, cha #endif /* BGP */ lac_initremotelnsdata(); + + grp_initdata(); } static int assign_ip_address(sessionidt s) @@@ -5075,9 -5055,9 +5088,9 @@@ int main(int argc, char *argv[] case 'd': if (fork()) exit(0); setsid(); - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); + if(!freopen("/dev/null", "r", stdin)) LOG(0, 0, 0, "Error freopen stdin: %s\n", strerror(errno)); + if(!freopen("/dev/null", "w", stdout)) LOG(0, 0, 0, "Error freopen stdout: %s\n", strerror(errno)); + if(!freopen("/dev/null", "w", stderr)) LOG(0, 0, 0, "Error freopen stderr: %s\n", strerror(errno)); break; case 'v': optdebug++; @@@ -5128,7 -5108,7 +5141,7 @@@ LOG(0, 0, 0, "Can't set ulimit: %s\n", strerror(errno)); // Make core dumps go to /tmp - chdir("/tmp"); + if(chdir("/tmp")) LOG(0, 0, 0, "Error chdir /tmp: %s\n", strerror(errno)); } if (config->scheduler_fifo) @@@ -5215,9 -5195,6 +5228,9 @@@ LOG(0, 0, 0, "Can't lock pages: %s\n", strerror(errno)); } + //LOG(3, 0, 0, "Debug sizeof struct: sessiont %lu, tunnelt %lu, bundlet %lu, groupsesst %lu\n", + // sizeof(sessiont), sizeof(tunnelt), sizeof(bundlet), sizeof(groupsesst)); + mainloop(); /* remove plugins (so cleanup code gets run) */ @@@ -5729,7 -5706,6 +5742,7 @@@ int sessionsetup(sessionidt s, tunnelid if (!session[s].bundle || (bundle[session[s].bundle].num_of_links == 1)) { int routed = 0; + groupidt g; // Add the route for this session. for (r = 0; r < MAXROUTE && session[s].route[r].ip; r++) @@@ -5752,12 -5728,6 +5765,12 @@@ } else cache_ipmap(session[s].ip, s); + + if ((g = grp_groupbysession(s))) + { + grp_setgrouproute(g, 1); + cluster_send_groupe(g); + } } sess_local[s].lcp_authtype = 0; // RADIUS authentication complete @@@ -5844,6 -5814,10 +5857,10 @@@ int load_session(sessionidt s, session uncache_ipmap(session[s].ip); } + // remove old IPV6 routes... + if (session[s].ipv6route.s6_addr[0] && session[s].ipv6prefixlen) + route6set(s, session[s].ipv6route, session[s].ipv6prefixlen, 0); + routed = 0; // add new routes... @@@ -6318,7 -6292,7 +6335,7 @@@ void become_master(void } } - int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc) + int cmd_show_hist_idle(struct cli_def *cli, const char *command, char **argv, int argc) { int s, i; int count = 0; @@@ -6356,7 -6330,7 +6373,7 @@@ return CLI_OK; } - int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc) + int cmd_show_hist_open(struct cli_def *cli, const char *command, char **argv, int argc) { int s, i; int count = 0; diff --combined l2tpns.h index 5dd854f,4f2f784..d28f3e7 --- a/l2tpns.h +++ b/l2tpns.h @@@ -24,9 -24,6 +24,9 @@@ #define MAXADDRESS 20 // Maximum length for the Endpoint Discrminiator address #define MAXSESSION 60000 // could be up to 65535 #define MAXTBFS 6000 // Maximum token bucket filters. Might need up to 2 * session. +#define MAXSESSINGRP 12 // Maximum number of member links in grouped session +#define MAXGROUPE 300 // could be up to 65535, Maximum number of grouped session +#define MAXROUTEINGRP 15 // max static routes per group // Tunnel Id reserved for pppoe #define TUNNEL_ID_PPPOE 1 @@@ -219,7 -216,6 +219,7 @@@ enum typedef uint16_t sessionidt; typedef uint16_t bundleidt; typedef uint16_t tunnelidt; +typedef uint16_t groupidt; typedef uint32_t clockt; typedef uint8_t hasht[16]; @@@ -337,39 -333,10 +337,39 @@@ typedef struc struct in6_addr ipv6route; // Static IPv6 route sessionidt forwardtosession; // LNS id_session to forward uint8_t src_hwaddr[ETH_ALEN]; // MAC addr source (for pppoe sessions 6 bytes) - char reserved[4]; // Space to expand structure without changing HB_VERSION + char reserved[4]; // Space to expand structure without changing HB_VERSION } sessiont; +typedef struct +{ + uint32_t tx_rate; + uint32_t prev_coutgrp; + sessionidt sid; + uint8_t weight; +} +groupsesslistt; + +typedef struct +{ + int state; // current state (groupestate enum) + uint32_t time_changed; + groupidt prev; + sessionidt smax; + sessionidt smin; + groupsesslistt sesslist[MAXSESSINGRP]; + routet route[MAXROUTEINGRP]; // static routes + uint8_t nbroutesgrp; + uint8_t nbsession; +} +groupsesst; + +union iphash +{ + sessionidt sess; + union iphash *idx; +}; // Mapping from IP address to session structures. + typedef struct { int state; // current state (bundlestate enum) @@@ -552,13 -519,6 +552,13 @@@ enu BUNDLEUNDEF, // Undefined }; +enum +{ + GROUPEFREE, // Not in use + GROUPEOPEN, // Active bundle + GROUPEUNDEF // Undefined +}; + enum { NULLCLASS = 0, //End Point Discriminator classes @@@ -767,10 -727,8 +767,10 @@@ typedef struc int cluster_undefined_sessions; // How many sessions we're yet to receive from the master. int cluster_undefined_bundles; // How many bundles we're yet to receive from the master. int cluster_undefined_tunnels; // How many tunnels we're yet to receive from the master. + int cluster_undefined_groupes; // How many groupes we're yet to receive from the master. int cluster_highest_sessionid; int cluster_highest_bundleid; + int cluster_highest_groupeid; int cluster_highest_tunnelid; clockt cluster_last_hb; // Last time we saw a heartbeat from the master. int cluster_last_hb_ver; // Heartbeat version last seen from master @@@ -825,7 -783,6 +825,7 @@@ int nbmultiaddress; // number multi address to bind int indexlacudpfd; // Index UDP LAC file handle (in udpfd[]) int nbmultihostname; // number hostname, normally the same number as the nbudpfd + int grp_txrate_average_time; // caculation txrate average time (default 10s) in_addr_t bind_n_address[MAX_BINDADDR]; in_addr_t iftun_n_address[MAX_BINDADDR]; char bind_multi_address[256]; @@@ -991,30 -948,15 +991,29 @@@ void processipout(uint8_t *buf, int len void snoop_send_packet(uint8_t *packet, uint16_t size, in_addr_t destination, uint16_t port); int find_filter(char const *name, size_t len); int ip_filter(uint8_t *buf, int len, uint8_t filter); - int cmd_show_ipcache(struct cli_def *cli, char *command, char **argv, int argc); - int cmd_show_hist_idle(struct cli_def *cli, char *command, char **argv, int argc); - int cmd_show_hist_open(struct cli_def *cli, char *command, char **argv, int argc); + int cmd_show_ipcache(struct cli_def *cli, const char *command, char **argv, int argc); + int cmd_show_hist_idle(struct cli_def *cli, const char *command, char **argv, int argc); + int cmd_show_hist_open(struct cli_def *cli, const char *command, char **argv, int argc); +void netlink_addattr(struct nlmsghdr *nh, int type, const void *data, int alen); +ssize_t netlink_send(struct nlmsghdr *nh); +void cache_ipmap(in_addr_t ip, sessionidt s); - tunnelidt lac_new_tunnel(); void lac_tunnelclear(tunnelidt t); void lac_send_SCCRQ(tunnelidt t, uint8_t * auth, unsigned int auth_len); void lac_send_ICRQ(tunnelidt t, sessionidt s); void lac_tunnelshutdown(tunnelidt t, char *reason, int result, int error, char *msg); +// grpsess.c +sessionidt grp_getnextsession(groupidt g, in_addr_t ip, in_addr_t ip_src); +void grp_initdata(void); +void grp_processvendorspecific(sessionidt s, uint8_t *pvs); +groupidt grp_groupbysession(sessionidt s); +groupidt grp_groupbyip(in_addr_t ip); +void grp_setgrouproute(groupidt g, int add); +void grp_time_changed(void); +void grp_removesession(groupidt g, sessionidt s); +int grp_cluster_load_groupe(groupidt g, groupsesst *new); + #undef LOG #undef LOG_HEX #define LOG(D, s, t, f, ...) ({ if (D <= config->debug) _log(D, s, t, f, ## __VA_ARGS__); }) @@@ -1049,8 -991,6 +1048,8 @@@ extern bundlet *bundle extern sessiont *session; extern sessionlocalt *sess_local; extern ippoolt *ip_address_pool; +extern groupsesst *grpsession; +extern groupidt gnextgrpid; #define sessionfree (session[0].next) @@@ -1063,8 -1003,6 +1062,8 @@@ extern struct Tstats *_statistics extern in_addr_t my_address; extern int clifd; extern int epollfd; +extern int tunidx; // ifr_ifindex of tun device +extern union iphash ip_hash[256]; struct event_data { enum { diff --combined tbf.c index 8b488d6,93e1025..aa9810e --- a/tbf.c +++ b/tbf.c @@@ -1,9 -1,6 +1,9 @@@ // L2TPNS: token bucket filters #include +#include +#include + #include "l2tpns.h" #include "util.h" #include "tbf.h" @@@ -310,7 -307,7 +310,7 @@@ int tbf_run_timer(void return 1; } - int cmd_show_tbf(struct cli_def *cli, char *command, char **argv, int argc) + int cmd_show_tbf(struct cli_def *cli, const char *command, char **argv, int argc) { int i; int count = 0;