update filter refcounts

add cli commands for filtering/unfiltering
This commit is contained in:
Brendan O'Dea 2004-11-28 02:53:11 +00:00
parent 5e337e7ed9
commit 6d5c3ecb4d
4 changed files with 258 additions and 29 deletions

190
cli.c
View file

@ -2,7 +2,7 @@
// vim: sw=8 ts=8 // vim: sw=8 ts=8
char const *cvs_name = "$Name: $"; char const *cvs_name = "$Name: $";
char const *cvs_id_cli = "$Id: cli.c,v 1.31 2004-11-27 21:10:50 bodea Exp $"; char const *cvs_id_cli = "$Id: cli.c,v 1.32 2004-11-28 02:53:11 bodea Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -115,6 +115,8 @@ static int cmd_restart_bgp(struct cli_def *cli, char *command, char **argv, int
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, 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_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_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);
/* match if b is a substr of a */ /* match if b is a substr of a */
#define MATCH(a,b) (!strncmp((a), (b), strlen(b))) #define MATCH(a,b) (!strncmp((a), (b), strlen(b)))
@ -169,8 +171,9 @@ void init_cli(char *hostname)
cli_register_command(cli, c, "memory", cmd_write_memory, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Save the running config to flash"); cli_register_command(cli, c, "memory", cmd_write_memory, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Save the running config to flash");
cli_register_command(cli, c, "terminal", cmd_show_run, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show the running config"); cli_register_command(cli, c, "terminal", cmd_show_run, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Show the running config");
cli_register_command(cli, NULL, "snoop", cmd_snoop, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Temporarily enable interception for a user"); cli_register_command(cli, NULL, "snoop", cmd_snoop, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Enable interception of a session");
cli_register_command(cli, NULL, "throttle", cmd_throttle, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Temporarily enable throttling for a user"); cli_register_command(cli, NULL, "throttle", cmd_throttle, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Enable throttling of a session");
cli_register_command(cli, NULL, "filter", cmd_filter, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Add filtering to a session");
cli_register_command(cli, NULL, "debug", cmd_debug, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Set the level of logging that is shown on the console"); cli_register_command(cli, NULL, "debug", cmd_debug, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Set the level of logging that is shown on the console");
#ifdef BGP #ifdef BGP
@ -179,8 +182,9 @@ void init_cli(char *hostname)
#endif /* BGP */ #endif /* BGP */
c = cli_register_command(cli, NULL, "no", NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL); c = cli_register_command(cli, NULL, "no", NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL);
cli_register_command(cli, c, "snoop", cmd_no_snoop, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Temporarily disable interception for a user"); cli_register_command(cli, c, "snoop", cmd_no_snoop, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Disable interception of a session");
cli_register_command(cli, c, "throttle", cmd_no_throttle, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Temporarily disable throttling for a user"); cli_register_command(cli, c, "throttle", cmd_no_throttle, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Disable throttling of a session");
cli_register_command(cli, c, "filter", cmd_no_filter, PRIVILEGE_PRIVILEGED, MODE_EXEC, "Remove filtering from a session");
cli_register_command(cli, c, "debug", cmd_no_debug, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Turn off logging of a certain level of debugging"); cli_register_command(cli, c, "debug", cmd_no_debug, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Turn off logging of a certain level of debugging");
#ifdef BGP #ifdef BGP
@ -406,9 +410,9 @@ static int cmd_show_session(struct cli_def *cli, char *command, char **argv, int
cli_print(cli, "\tRx Speed:\t%lu", session[s].rx_connect_speed); cli_print(cli, "\tRx Speed:\t%lu", session[s].rx_connect_speed);
cli_print(cli, "\tTx Speed:\t%lu", session[s].tx_connect_speed); cli_print(cli, "\tTx Speed:\t%lu", session[s].tx_connect_speed);
if (session[s].filter_in && session[s].filter_in <= MAXFILTER) if (session[s].filter_in && session[s].filter_in <= MAXFILTER)
cli_print(cli, "\tFilter in:\t%u (%s)", session[s].filter_in, ip_filters[session[s].filter_in-1].name); cli_print(cli, "\tFilter in:\t%u (%s)", session[s].filter_in, ip_filters[session[s].filter_in - 1].name);
if (session[s].filter_out && session[s].filter_out <= MAXFILTER) if (session[s].filter_out && session[s].filter_out <= MAXFILTER)
cli_print(cli, "\tFilter out:\t%u (%s)", session[s].filter_out, ip_filters[session[s].filter_out-1].name); cli_print(cli, "\tFilter out:\t%u (%s)", session[s].filter_out, ip_filters[session[s].filter_out - 1].name);
if (session[s].snoop_ip && session[s].snoop_port) if (session[s].snoop_ip && session[s].snoop_port)
cli_print(cli, "\tIntercepted:\t%s:%d", inet_toa(session[s].snoop_ip), session[s] .snoop_port); cli_print(cli, "\tIntercepted:\t%s:%d", inet_toa(session[s].snoop_ip), session[s] .snoop_port);
else else
@ -1426,11 +1430,10 @@ static int cmd_throttle(struct cli_def *cli, char *command, char **argv, int arg
int i; int i;
for (i = 1; i < argc - 1; i += 2) for (i = 1; i < argc - 1; i += 2)
{ {
int len = strlen(argv[i]);
int r = 0; int r = 0;
if (!strncasecmp(argv[i], "in", len)) if (MATCH("in", argv[i]))
r = rate_in = atoi(argv[i+1]); r = rate_in = atoi(argv[i+1]);
else if (!strncasecmp(argv[i], "out", len)) else if (MATCH("out", argv[i]))
r = rate_out = atoi(argv[i+1]); r = rate_out = atoi(argv[i+1]);
if (r < 1) if (r < 1)
@ -1560,13 +1563,13 @@ static int cmd_debug(struct cli_def *cli, char *command, char **argv, int argc)
if (argv[i][0] == 'c' && len < 2) if (argv[i][0] == 'c' && len < 2)
len = 2; /* distinguish [cr]itical from [ca]lls */ len = 2; /* distinguish [cr]itical from [ca]lls */
if (!strncasecmp(argv[i], "critical", len)) { debug_flags.critical = 1; continue; } if (!strncmp("critical", argv[i], len)) { debug_flags.critical = 1; continue; }
if (!strncasecmp(argv[i], "error", len)) { debug_flags.error = 1; continue; } if (!strncmp("error", argv[i], len)) { debug_flags.error = 1; continue; }
if (!strncasecmp(argv[i], "warning", len)) { debug_flags.warning = 1; continue; } if (!strncmp("warning", argv[i], len)) { debug_flags.warning = 1; continue; }
if (!strncasecmp(argv[i], "info", len)) { debug_flags.info = 1; continue; } if (!strncmp("info", argv[i], len)) { debug_flags.info = 1; continue; }
if (!strncasecmp(argv[i], "calls", len)) { debug_flags.calls = 1; continue; } if (!strncmp("calls", argv[i], len)) { debug_flags.calls = 1; continue; }
if (!strncasecmp(argv[i], "data", len)) { debug_flags.data = 1; continue; } if (!strncmp("data", argv[i], len)) { debug_flags.data = 1; continue; }
if (!strncasecmp(argv[i], "all", len)) if (!strncmp("all", argv[i], len))
{ {
memset(&debug_flags, 1, sizeof(debug_flags)); memset(&debug_flags, 1, sizeof(debug_flags));
debug_flags.data = 0; debug_flags.data = 0;
@ -1607,13 +1610,13 @@ static int cmd_no_debug(struct cli_def *cli, char *command, char **argv, int arg
if (argv[i][0] == 'c' && len < 2) if (argv[i][0] == 'c' && len < 2)
len = 2; /* distinguish [cr]itical from [ca]lls */ len = 2; /* distinguish [cr]itical from [ca]lls */
if (!strncasecmp(argv[i], "critical", len)) { debug_flags.critical = 0; continue; } if (!strncmp("critical", argv[i], len)) { debug_flags.critical = 0; continue; }
if (!strncasecmp(argv[i], "error", len)) { debug_flags.error = 0; continue; } if (!strncmp("error", argv[i], len)) { debug_flags.error = 0; continue; }
if (!strncasecmp(argv[i], "warning", len)) { debug_flags.warning = 0; continue; } if (!strncmp("warning", argv[i], len)) { debug_flags.warning = 0; continue; }
if (!strncasecmp(argv[i], "info", len)) { debug_flags.info = 0; continue; } if (!strncmp("info", argv[i], len)) { debug_flags.info = 0; continue; }
if (!strncasecmp(argv[i], "calls", len)) { debug_flags.calls = 0; continue; } if (!strncmp("calls", argv[i], len)) { debug_flags.calls = 0; continue; }
if (!strncasecmp(argv[i], "data", len)) { debug_flags.data = 0; continue; } if (!strncmp("data", argv[i], len)) { debug_flags.data = 0; continue; }
if (!strncasecmp(argv[i], "all", len)) if (!strncmp("all", argv[i], len))
{ {
memset(&debug_flags, 0, sizeof(debug_flags)); memset(&debug_flags, 0, sizeof(debug_flags));
continue; continue;
@ -1769,7 +1772,7 @@ static int cmd_set(struct cli_def *cli, char *command, char **argv, int argc)
{ {
int len = strlen(argv[0])-1; int len = strlen(argv[0])-1;
for (i = 0; config_values[i].key; i++) for (i = 0; config_values[i].key; i++)
if (!len || !strncmp(argv[0], config_values[i].key, len)) if (!len || !strncmp(config_values[i].key, argv[0], len))
cli_print(cli, " %s", config_values[i].key); cli_print(cli, " %s", config_values[i].key);
} }
@ -2826,6 +2829,143 @@ static int cmd_ip_access_list_rule(struct cli_def *cli, char *command, char **ar
return CLI_OK; return CLI_OK;
} }
static int cmd_filter(struct cli_def *cli, char *command, char **argv, int argc)
{
sessionidt s;
int i;
/* filter USER {in|out} FILTER ... */
if (CLI_HELP_REQUESTED)
{
switch (argc)
{
case 1:
return cli_arg_help(cli, 0,
"USER", "Username of session to filter", NULL);
case 2:
case 4:
return cli_arg_help(cli, 0,
"in", "Set incoming filter",
"out", "Set outgoing filter", NULL);
case 3:
case 5:
return cli_arg_help(cli, argc == 5 && argv[4][1],
"NAME", "Filter name", NULL);
default:
return cli_arg_help(cli, argc > 1, NULL);
}
}
if (!config->cluster_iam_master)
{
cli_print(cli, "Can't do this on a slave. Do it on %s", inet_toa(config->cluster_master_address));
return CLI_OK;
}
if (argc != 3 && argc != 5)
{
cli_print(cli, "Specify a user and filters");
return CLI_OK;
}
if (!(s = sessionbyuser(argv[0])))
{
cli_print(cli, "User %s is not connected", argv[0]);
return CLI_OK;
}
cli_session_actions[s].filter_in = cli_session_actions[s].filter_out = -1;
for (i = 1; i < argc; i += 2)
{
int *f = 0;
int v;
if (MATCH("in", argv[i]))
{
if (session[s].filter_in)
{
cli_print(cli, "Input already filtered");
return CLI_OK;
}
f = &cli_session_actions[s].filter_in;
}
else if (MATCH("out", argv[i]))
{
if (session[s].filter_out)
{
cli_print(cli, "Output already filtered");
return CLI_OK;
}
f = &cli_session_actions[s].filter_out;
}
else
{
cli_print(cli, "Invalid filter specification");
return CLI_OK;
}
v = find_access_list(argv[i+1]);
if (v < 0 || !*ip_filters[v].name)
{
cli_print(cli, "Access-list %s not defined", argv[i+1]);
return CLI_OK;
}
*f = v + 1;
}
cli_print(cli, "Filtering user %s", argv[0]);
cli_session_actions[s].action |= CLI_SESS_FILTER;
return CLI_OK;
}
static int cmd_no_filter(struct cli_def *cli, char *command, char **argv, int argc)
{
int i;
sessionidt s;
if (CLI_HELP_REQUESTED)
return cli_arg_help(cli, argc > 1,
"USER", "Username of session to remove filters from", NULL);
if (!config->cluster_iam_master)
{
cli_print(cli, "Can't do this on a slave. Do it on %s", inet_toa(config->cluster_master_address));
return CLI_OK;
}
if (!argc)
{
cli_print(cli, "Specify a user to remove filters from");
return CLI_OK;
}
for (i = 0; i < argc; i++)
{
if (!(s = sessionbyuser(argv[i])))
{
cli_print(cli, "User %s is not connected", argv[i]);
continue;
}
if (session[s].filter_in || session[s].filter_out)
{
cli_print(cli, "Removing filters from user %s", argv[i]);
cli_session_actions[s].action |= CLI_SESS_NOFILTER;
}
else
{
cli_print(cli, "User %s not filtered", argv[i]);
}
}
return CLI_OK;
}
// Convert a string in the form of abcd.ef12.3456 into char[6] // Convert a string in the form of abcd.ef12.3456 into char[6]
void parsemac(char *string, char mac[6]) void parsemac(char *string, char mac[6])
{ {

View file

@ -4,7 +4,7 @@
// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8 // vim: sw=8 ts=8
char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.57 2004-11-27 05:19:53 bodea Exp $"; char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.58 2004-11-28 02:53:11 bodea Exp $";
#include <arpa/inet.h> #include <arpa/inet.h>
#include <assert.h> #include <assert.h>
@ -1002,6 +1002,44 @@ void throttle_session(sessionidt s, int rate_in, int rate_out)
} }
} }
// add/remove filters from session (-1 = no change)
void filter_session(sessionidt s, int filter_in, int filter_out)
{
if (!session[s].tunnel)
return; // No-one home.
if (!*session[s].user)
return; // User not logged in
// paranoia
if (filter_in > MAXFILTER) filter_in = -1;
if (filter_out > MAXFILTER) filter_out = -1;
if (session[s].filter_in > MAXFILTER) session[s].filter_in = 0;
if (session[s].filter_out > MAXFILTER) session[s].filter_out = 0;
if (filter_in >= 0)
{
if (session[s].filter_in)
ip_filters[session[s].filter_in - 1].used--;
if (filter_in > 0)
ip_filters[filter_in - 1].used++;
session[s].filter_in = filter_in;
}
if (filter_out >= 0)
{
if (session[s].filter_out)
ip_filters[session[s].filter_out - 1].used--;
if (filter_out > 0)
ip_filters[filter_out - 1].used++;
session[s].filter_out = filter_out;
}
}
// start tidy shutdown of session // start tidy shutdown of session
void sessionshutdown(sessionidt s, char *reason) void sessionshutdown(sessionidt s, char *reason)
{ {
@ -1081,6 +1119,10 @@ void sessionshutdown(sessionidt s, char *reason)
if (!session[s].die) if (!session[s].die)
session[s].die = now() + 150; // Clean up in 15 seconds session[s].die = now() + 150; // Clean up in 15 seconds
// update filter refcounts
if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--;
if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--;
cluster_send_session(s); cluster_send_session(s);
} }
@ -2131,6 +2173,22 @@ static int regular_cleanups(void)
send++; send++;
} }
if (a & CLI_SESS_NOFILTER)
{
LOG(2, 0, s, session[s].tunnel, "Un-filtering session by CLI\n");
filter_session(s, 0, 0);
send++;
}
else if (a & CLI_SESS_FILTER)
{
LOG(2, 0, s, session[s].tunnel, "Filtering session by CLI (in=%d, out=%d)\n",
cli_session_actions[s].filter_in,
cli_session_actions[s].filter_out);
filter_session(s, cli_session_actions[s].filter_in, cli_session_actions[s].filter_out);
send++;
}
if (send) if (send)
cluster_send_session(s); cluster_send_session(s);
@ -3729,6 +3787,31 @@ int load_session(sessionidt s, sessiont *new)
} }
} }
// check filters
if (new->filter_in && (new->filter_in > MAXFILTER || !ip_filters[new->filter_in - 1].name[0]))
{
LOG(2, session[s].ip, s, session[s].tunnel, "Dropping invalid input filter %d\n", (int) new->filter_in);
new->filter_in = 0;
}
if (new->filter_out && (new->filter_out > MAXFILTER || !ip_filters[new->filter_out - 1].name[0]))
{
LOG(2, session[s].ip, s, session[s].tunnel, "Dropping invalid output filter %d\n", (int) new->filter_out);
new->filter_out = 0;
}
if (new->filter_in != session[s].filter_in)
{
if (session[s].filter_in) ip_filters[session[s].filter_in - 1].used--;
if (new->filter_in) ip_filters[new->filter_in - 1].used++;
}
if (new->filter_out != session[s].filter_out)
{
if (session[s].filter_out) ip_filters[session[s].filter_out - 1].used--;
if (new->filter_out) ip_filters[new->filter_out - 1].used++;
}
if (new->tunnel && s > config->cluster_highest_sessionid) // Maintain this in the slave. It's used if (new->tunnel && s > config->cluster_highest_sessionid) // Maintain this in the slave. It's used
// for walking the sessions to forward byte counts to the master. // for walking the sessions to forward byte counts to the master.
config->cluster_highest_sessionid = s; config->cluster_highest_sessionid = s;

View file

@ -1,5 +1,5 @@
// L2TPNS Global Stuff // L2TPNS Global Stuff
// $Id: l2tpns.h,v 1.38 2004-11-27 05:19:53 bodea Exp $ // $Id: l2tpns.h,v 1.39 2004-11-28 02:53:11 bodea Exp $
#ifndef __L2TPNS_H__ #ifndef __L2TPNS_H__
#define __L2TPNS_H__ #define __L2TPNS_H__
@ -124,6 +124,8 @@ struct cli_session_actions {
u16 snoop_port; u16 snoop_port;
int throttle_in; int throttle_in;
int throttle_out; int throttle_out;
int filter_in;
int filter_out;
}; };
#define CLI_SESS_KILL 0x01 #define CLI_SESS_KILL 0x01
@ -131,6 +133,8 @@ struct cli_session_actions {
#define CLI_SESS_NOSNOOP 0x04 #define CLI_SESS_NOSNOOP 0x04
#define CLI_SESS_THROTTLE 0x08 #define CLI_SESS_THROTTLE 0x08
#define CLI_SESS_NOTHROTTLE 0x10 #define CLI_SESS_NOTHROTTLE 0x10
#define CLI_SESS_FILTER 0x20
#define CLI_SESS_NOFILTER 0x40
struct cli_tunnel_actions { struct cli_tunnel_actions {
char action; char action;

View file

@ -1,6 +1,6 @@
// L2TPNS Radius Stuff // L2TPNS Radius Stuff
char const *cvs_id_radius = "$Id: radius.c,v 1.16 2004-11-27 21:10:51 bodea Exp $"; char const *cvs_id_radius = "$Id: radius.c,v 1.17 2004-11-28 02:53:11 bodea Exp $";
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
@ -573,7 +573,9 @@ void processrad(u8 *buf, int len, char socket_index)
!strncmp(ip_filters[i].name, filter, l)) !strncmp(ip_filters[i].name, filter, l))
*f = i + 1; *f = i + 1;
if (!*f) if (*f)
ip_filters[*f - 1].used++;
else
LOG(3, 0, s, session[s].tunnel, " Unknown filter\n"); LOG(3, 0, s, session[s].tunnel, " Unknown filter\n");
} }