From dff48db0782444125f68cab14d91e7bb4109286a Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Sun, 19 Nov 2017 18:06:58 -0800 Subject: session/tcp: filtering improvements - make allow action explicit (-3) - add session lookup is_filtered return flag that is set if lookup hit a deny filter - change tcp logic to drop filtered packets when punting is enabled Change-Id: Ic38f294424663a4e108439b7571511f46f8e0be1 Signed-off-by: Florin Coras --- src/vnet/session/application_namespace.c | 8 +- src/vnet/session/session_lookup.c | 152 +++++++++++++++++-------------- src/vnet/session/session_lookup.h | 6 +- src/vnet/session/session_rules_table.h | 4 +- src/vnet/session/session_test.c | 140 ++++++++++++++++++++++------ src/vnet/tcp/tcp_error.def | 3 +- src/vnet/tcp/tcp_input.c | 36 +++++--- src/vnet/tcp/tcp_test.c | 12 +-- 8 files changed, 234 insertions(+), 127 deletions(-) (limited to 'src/vnet') diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c index eaf09e8e369..21c1cbc92c6 100644 --- a/src/vnet/session/application_namespace.c +++ b/src/vnet/session/application_namespace.c @@ -248,7 +248,8 @@ u8 * format_app_namespace (u8 * s, va_list * args) { app_namespace_t *app_ns = va_arg (*args, app_namespace_t *); - s = format (s, "%-20v%-20lu%-20u", app_ns->ns_id, app_ns->ns_secret, + s = format (s, "%-20v%-10u%-20lu%-20u", app_ns->ns_id, + app_namespace_index (app_ns), app_ns->ns_secret, app_ns->sw_if_index); return s; } @@ -301,9 +302,10 @@ show_app_ns_fn (vlib_main_t * vm, unformat_input_t * main_input, goto done; } - vlib_cli_output (vm, "%-20s%-20s%-20s", "Namespace", "Secret", - "sw_if_index"); do_ns_list: + vlib_cli_output (vm, "%-20s%-10s%-20s%-20s", "Namespace", "Index", "Secret", + "sw_if_index"); + /* *INDENT-OFF* */ pool_foreach (app_ns, app_namespace_pool, ({ vlib_cli_output (vm, "%U", format_app_namespace, app_ns); diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 30e39132d3a..2e4e96a4dea 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -378,12 +378,28 @@ session_lookup_del_session (stream_session_t * s) return session_lookup_del_connection (ts); } +static u8 +session_lookup_action_index_is_valid (u32 action_index) +{ + if (action_index == SESSION_RULES_TABLE_ACTION_ALLOW + || action_index == SESSION_RULES_TABLE_INVALID_INDEX) + return 0; + return 1; +} + static u32 -session_lookup_action_to_session_index (u32 action_index) +session_lookup_action_to_app_index (u32 action_index) { - if (action_index != SESSION_RULES_TABLE_ACTION_DROP) - return action_index; - return SESSION_INVALID_INDEX; + switch (action_index) + { + case SESSION_RULES_TABLE_ACTION_DROP: + return APP_DROP_INDEX; + case SESSION_RULES_TABLE_ACTION_ALLOW: + case SESSION_RULES_TABLE_INVALID_INDEX: + return APP_INVALID_INDEX; + default: + return action_index; + } } static stream_session_t * @@ -391,7 +407,7 @@ session_lookup_app_listen_session (u32 app_index, u8 fib_proto, u8 transport_proto) { application_t *app; - app = application_get (app_index); + app = application_get_if_valid (app_index); if (!app) return 0; @@ -402,10 +418,10 @@ static stream_session_t * session_lookup_action_to_session (u32 action_index, u8 fib_proto, u8 transport_proto) { - u32 session_index; - session_index = session_lookup_action_to_session_index (action_index); + u32 app_index; + app_index = session_lookup_action_to_app_index (action_index); /* Nothing sophisticated for now, action index is app index */ - return session_lookup_app_listen_session (session_index, fib_proto, + return session_lookup_app_listen_session (app_index, fib_proto, transport_proto); } @@ -415,26 +431,26 @@ session_lookup_rules_table_session4 (session_table_t * st, u8 proto, ip4_address_t * rmt, u16 rmt_port) { session_rules_table_t *srt = &st->session_rules[proto]; - u32 action_index, session_index; + u32 action_index, app_index; action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port, rmt_port); - session_index = session_lookup_action_to_session_index (action_index); + app_index = session_lookup_action_to_app_index (action_index); /* Nothing sophisticated for now, action index is app index */ - return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP4, + return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4, proto); } stream_session_t * -session_lookup_rules_table6 (session_table_t * st, u8 proto, - ip6_address_t * lcl, u16 lcl_port, - ip6_address_t * rmt, u16 rmt_port) +session_lookup_rules_table_session6 (session_table_t * st, u8 proto, + ip6_address_t * lcl, u16 lcl_port, + ip6_address_t * rmt, u16 rmt_port) { session_rules_table_t *srt = &st->session_rules[proto]; - u32 action_index, session_index; + u32 action_index, app_index; action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port, rmt_port); - session_index = session_lookup_action_to_session_index (action_index); - return session_lookup_app_listen_session (session_index, FIB_PROTOCOL_IP6, + app_index = session_lookup_action_to_app_index (action_index); + return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6, proto); } @@ -477,8 +493,8 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, srt = &st->session_rules[sep->transport_proto]; ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session_index (ai); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_app_index (ai); } } else @@ -497,8 +513,8 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, srt = &st->session_rules[sep->transport_proto]; ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, sep->port); - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session_index (ai); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_app_index (ai); } } return SESSION_INVALID_HANDLE; @@ -545,10 +561,8 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) srt = &st->session_rules[sep->transport_proto]; ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, sep->port); - if (ai == SESSION_RULES_TABLE_ACTION_DROP) - return APP_DROP_INDEX; - if (ai != SESSION_RULES_TABLE_ACTION_NONE) - return session_lookup_action_to_session_index (ai); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_app_index (ai); /* * Check if session endpoint is a listener @@ -585,10 +599,8 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) srt = &st->session_rules[sep->transport_proto]; ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, sep->port); - if (ai == SESSION_RULES_TABLE_ACTION_DROP) - return APP_DROP_INDEX; - if (ai != SESSION_RULES_TABLE_INVALID_INDEX) - return session_lookup_action_to_session_index (ai); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_app_index (ai); make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sep->transport_proto); @@ -828,13 +840,15 @@ session_lookup_half_open_connection (u64 handle, u8 proto, u8 is_ip4) * @param rmt_port remote port * @param proto transport protocol (e.g., tcp, udp) * @param thread_index thread index for request + * @param is_filtered return flag that indicates if connection was filtered. * * @return pointer to transport connection, if one is found, 0 otherwise */ transport_connection_t * session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, u16 lcl_port, - u16 rmt_port, u8 proto, u32 thread_index) + u16 rmt_port, u8 proto, u32 thread_index, + u8 * is_filtered) { session_table_t *st; session_kv4_t kv4; @@ -874,14 +888,14 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, */ action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, rmt, lcl_port, rmt_port); - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + if (session_lookup_action_index_is_valid (action_index)) { - s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto); - if (s) + if ((*is_filtered = (action_index == SESSION_RULES_TABLE_ACTION_DROP))) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) return tp_vfts[s->session_type].get_listener (s->connection_index); + return 0; } /* @@ -952,14 +966,14 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, */ action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, rmt, lcl_port, rmt_port); - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + if (session_lookup_action_index_is_valid (action_index)) { - s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto); - if (s) + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) return tp_vfts[s->session_type].get_listener (s->connection_index); + return 0; } /* @@ -1012,13 +1026,12 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, */ action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, rmt, lcl_port, rmt_port); - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + if (session_lookup_action_index_is_valid (action_index)) { - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP4, proto))) - return s; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, + proto); } /* @@ -1058,7 +1071,8 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, transport_connection_t * session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, u16 lcl_port, - u16 rmt_port, u8 proto, u32 thread_index) + u16 rmt_port, u8 proto, u32 thread_index, + u8 * is_filtered) { session_table_t *st; stream_session_t *s; @@ -1091,14 +1105,14 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, /* Check the session rules table */ action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, rmt, lcl_port, rmt_port); - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + if (session_lookup_action_index_is_valid (action_index)) { - s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto); - if (s) + if ((*is_filtered = (action_index == SESSION_RULES_TABLE_ACTION_DROP))) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) return tp_vfts[s->session_type].get_listener (s->connection_index); + return 0; } /* If nothing is found, check if any listener is available */ @@ -1160,14 +1174,14 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, /* Check the session rules table */ action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, rmt, lcl_port, rmt_port); - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + if (session_lookup_action_index_is_valid (action_index)) { - s = session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto); - if (s) + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) return tp_vfts[s->session_type].get_listener (s->connection_index); + return 0; } /* If nothing is found, check if any listener is available */ @@ -1213,14 +1227,12 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, /* Check the session rules table */ action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, rmt, lcl_port, rmt_port); - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if (action_index != SESSION_RULES_TABLE_ACTION_NONE) + if (session_lookup_action_index_is_valid (action_index)) { - if ((s = - session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto))) - return s; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6, + proto); } /* If nothing is found, check if any listener is available */ @@ -1639,8 +1651,8 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, VLIB_CLI_COMMAND (show_session_rules_command, static) = { .path = "show session rules", - .short_help = "show session rules [appns proto " - " ]", + .short_help = "show session rules [ appns " + " scope ]", .function = show_session_rules_command_fn, }; /* *INDENT-ON* */ diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 00ef19fec5a..1bdf6d17fcb 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -32,7 +32,8 @@ transport_connection_t *session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * rmt, u16 lcl_port, u16 rmt_port, u8 proto, - u32 thread_index); + u32 thread_index, + u8 * is_filtered); transport_connection_t *session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, @@ -43,7 +44,8 @@ transport_connection_t *session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * rmt, u16 lcl_port, u16 rmt_port, u8 proto, - u32 thread_index); + u32 thread_index, + u8 * is_filtered); transport_connection_t *session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, diff --git a/src/vnet/session/session_rules_table.h b/src/vnet/session/session_rules_table.h index ecd2d9b14d6..9088afcca27 100644 --- a/src/vnet/session/session_rules_table.h +++ b/src/vnet/session/session_rules_table.h @@ -56,8 +56,8 @@ typedef CLIB_PACKED (struct #define SESSION_RULE_TAG_MAX_LEN 64 #define SESSION_RULES_TABLE_INVALID_INDEX MMA_TABLE_INVALID_INDEX -#define SESSION_RULES_TABLE_ACTION_DROP (((u32)~0) - 1) -#define SESSION_RULES_TABLE_ACTION_NONE SESSION_RULES_TABLE_INVALID_INDEX +#define SESSION_RULES_TABLE_ACTION_DROP (MMA_TABLE_INVALID_INDEX - 1) +#define SESSION_RULES_TABLE_ACTION_ALLOW (MMA_TABLE_INVALID_INDEX - 2) typedef struct _session_rules_table_add_del_args { diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c index 8194a313dc2..58d0d28ff6c 100644 --- a/src/vnet/session/session_test.c +++ b/src/vnet/session/session_test.c @@ -496,7 +496,8 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) * Cleanup */ vec_free (ns_id); - vnet_delete_loopback_interface (sw_if_index); + /* fails in multi core scenarions .. */ + /* vnet_delete_loopback_interface (sw_if_index); */ return 0; } @@ -780,11 +781,11 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) transport_connection_t *tc; u32 dummy_port = 1111; clib_error_t *error = 0; - u8 segment_name[128]; + u8 segment_name[128], is_filtered = 0; stream_session_t *listener, *s; app_namespace_t *default_ns = app_namespace_get_default (); u32 local_ns_index = default_ns->local_table_index; - int verbose = 0; + int verbose = 0, rv; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -852,7 +853,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "optimized lookup should not work (port)"); /* @@ -878,7 +880,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) "optimized lookup should return the listener"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc->c_index == listener->connection_index), "lookup should return the listener"); s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, @@ -897,7 +900,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port + 1, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "optimized lookup for wrong lcl port + 1 should not work"); @@ -911,7 +915,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) args.table_args.action_index); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port + 1, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc->c_index == listener->connection_index), "optimized lookup for lcl port + 1 should work"); app_index = session_lookup_local_endpoint (local_ns_index, &sep); @@ -923,12 +928,12 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) */ args.table_args.lcl_port = 1234; args.table_args.lcl.fp_addr.ip4 = lcl_ip; - args.table_args.lcl.fp_len = 32; + args.table_args.lcl.fp_len = 30; args.table_args.rmt.fp_addr.ip4 = rmt_ip; - args.table_args.rmt.fp_len = 32; + args.table_args.rmt.fp_len = 30; args.table_args.action_index = SESSION_RULES_TABLE_ACTION_DROP; error = vnet_session_rule_add_del (&args); - SESSION_TEST ((error == 0), "Add 1.2.3.4/32 1234 5.6.7.8/32 4321 action %d", + SESSION_TEST ((error == 0), "Add 1.2.3.4/30 1234 5.6.7.8/30 4321 action %d", args.table_args.action_index); if (verbose) @@ -941,26 +946,97 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 " "should fail (deny rule)"); + SESSION_TEST ((is_filtered == 1), "lookup should be filtered (deny)"); + app_index = session_lookup_local_endpoint (local_ns_index, &sep); SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234 " "5.6.7.8/16 4321 in local table should return deny"); - tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, - &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); - SESSION_TEST ((tc == 0), - "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 should not work"); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port + 1, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc->c_index == listener->connection_index), "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should work"); + /* + * "Mask" deny rule with more specific allow: + * Add allow rule 1.2.3.4/32 1234 5.6.7.8/32 4321 action -3 (allow) + */ + args.table_args.is_add = 1; + args.table_args.lcl_port = 1234; + args.table_args.lcl.fp_addr.ip4 = lcl_ip; + args.table_args.lcl.fp_len = 32; + args.table_args.rmt.fp_addr.ip4 = rmt_ip; + args.table_args.rmt.fp_len = 32; + args.table_args.action_index = SESSION_RULES_TABLE_ACTION_ALLOW; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Add masking rule 1.2.3.4/30 1234 5.6.7.8/32 " + "4321 action %d", args.table_args.action_index); + + is_filtered = 0; + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); + SESSION_TEST ((tc == 0), "lookup for 1.2.3.4/32 1234 5.6.7.8/16 4321 " + "should fail (allow without app)"); + SESSION_TEST ((is_filtered == 0), "lookup should NOT be filtered"); + + app_index = session_lookup_local_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == APP_INVALID_INDEX), "lookup for 1.2.3.4/32 1234" + " 5.6.7.8/16 4321 in local table should return invalid"); + + if (verbose) + { + vlib_cli_output (vm, "Local rules"); + session_lookup_dump_local_rules_table (local_ns_index, FIB_PROTOCOL_IP4, + TRANSPORT_PROTO_TCP); + } + + sep.ip.ip4.as_u32 += 1 << 24; + app_index = session_lookup_local_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == APP_DROP_INDEX), "lookup for 1.2.3.4/32 1234" + " 5.6.7.9/16 4321 in local table should return invalid"); + + vnet_connect_args_t connect_args = { + .sep = sep, + .app_index = attach_args.app_index, + .api_context = 0, + }; + + /* Try connecting */ + error = vnet_connect (&connect_args); + SESSION_TEST ((error != 0), "connect should fail"); + rv = clib_error_get_code (error); + SESSION_TEST ((rv == VNET_API_ERROR_APP_CONNECT_FILTERED), + "connect should be filtered"); + + sep.ip.ip4.as_u32 -= 1 << 24; + + + + /* + * Delete masking rule: 1.2.3.4/32 1234 5.6.7.8/32 4321 allow + */ + args.table_args.is_add = 0; + args.table_args.lcl_port = 1234; + args.table_args.lcl.fp_addr.ip4 = lcl_ip; + args.table_args.lcl.fp_len = 32; + args.table_args.rmt.fp_addr.ip4 = rmt_ip; + args.table_args.rmt.fp_len = 32; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 allow"); + + /* * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index */ + args.table_args.is_add = 1; args.table_args.lcl_port = 0; args.table_args.lcl.fp_len = 0; args.table_args.rmt.fp_len = 16; @@ -979,7 +1055,7 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) app_index = session_lookup_local_endpoint (local_ns_index, &sep); SESSION_TEST ((app_index == APP_DROP_INDEX), - "local session endpoint lookup " "should return deny"); + "local session endpoint lookup should return deny"); /* * Delete 1.2.3.4/32 1234 5.6.7.8/32 4321 deny @@ -987,9 +1063,9 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) args.table_args.is_add = 0; args.table_args.lcl_port = 1234; args.table_args.lcl.fp_addr.ip4 = lcl_ip; - args.table_args.lcl.fp_len = 32; + args.table_args.lcl.fp_len = 30; args.table_args.rmt.fp_addr.ip4 = rmt_ip; - args.table_args.rmt.fp_len = 32; + args.table_args.rmt.fp_len = 30; error = vnet_session_rule_add_del (&args); SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny"); @@ -1028,7 +1104,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port + 1, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 123*5* 5.6.7.8/16 4321 should not " "work (del)"); @@ -1044,14 +1121,16 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should " "not work (del + deny)"); SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 deny"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should" " not work (no-rule)"); @@ -1079,7 +1158,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) } tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc->c_index == listener->connection_index), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should work"); @@ -1097,7 +1177,8 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) "tag test_rule"); tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, lcl_port, - rmt_port, TRANSPORT_PROTO_TCP, 0); + rmt_port, TRANSPORT_PROTO_TCP, 0, + &is_filtered); SESSION_TEST ((tc == 0), "lookup 1.2.3.4/32 1234 5.6.7.8/16 4321 should not" " work (del)"); vec_free (args.table_args.tag); @@ -1118,7 +1199,7 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) u32 server_index, app_index; u32 dummy_server_api_index = ~0, sw_if_index = 0; clib_error_t *error = 0; - u8 segment_name[128], intf_mac[6], sst; + u8 segment_name[128], intf_mac[6], sst, is_filtered = 0; stream_session_t *s; transport_connection_t *tc; u16 lcl_port = 1234, rmt_port = 4321; @@ -1202,7 +1283,7 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) } tc = session_lookup_connection_wt4 (0, &lcl_ip, &rmt_ip, lcl_port, rmt_port, - TRANSPORT_PROTO_TCP, 0); + TRANSPORT_PROTO_TCP, 0, &is_filtered); SESSION_TEST ((tc != 0), "lookup 1.2.3.4 1234 5.6.7.8 4321 should be " "successful"); sst = session_type_from_proto_and_ip (TRANSPORT_PROTO_TCP, 1); @@ -1211,7 +1292,7 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) " server"); tc = session_lookup_connection_wt4 (0, &rmt_ip, &rmt_ip, lcl_port, rmt_port, - TRANSPORT_PROTO_TCP, 0); + TRANSPORT_PROTO_TCP, 0, &is_filtered); SESSION_TEST ((tc == 0), "lookup 5.6.7.8 1234 5.6.7.8 4321 should" " not work"); @@ -1237,7 +1318,8 @@ session_test_proxy (vlib_main_t * vm, unformat_input_t * input) app_index = session_lookup_local_endpoint (app_ns->local_table_index, &sep); SESSION_TEST ((app_index == SESSION_RULES_TABLE_INVALID_INDEX), "local session endpoint lookup should not work after detach"); - unformat_free (&tmp_input); + if (verbose) + unformat_free (&tmp_input); return 0; } diff --git a/src/vnet/tcp/tcp_error.def b/src/vnet/tcp/tcp_error.def index a179717ff13..5bff5ee5d4a 100644 --- a/src/vnet/tcp/tcp_error.def +++ b/src/vnet/tcp/tcp_error.def @@ -40,4 +40,5 @@ tcp_error (INVALID_CONNECTION, "Invalid connection") tcp_error (NO_WND, "No window") tcp_error (CONNECTION_CLOSED, "Connection closed") tcp_error (CREATE_EXISTS, "Connection already exists") -tcp_error (PUNT, "Packets punted") \ No newline at end of file +tcp_error (PUNT, "Packets punted") +tcp_error (FILTERED, "Packets filtered") \ No newline at end of file diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index 6d7bebadfeb..d3db7ef1eec 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -1902,6 +1902,7 @@ tcp_lookup_connection (u32 fib_index, vlib_buffer_t * b, u8 thread_index, tcp_header_t *tcp; transport_connection_t *tconn; tcp_connection_t *tc; + u8 is_filtered = 0; if (is_ip4) { ip4_header_t *ip4; @@ -1913,7 +1914,7 @@ tcp_lookup_connection (u32 fib_index, vlib_buffer_t * b, u8 thread_index, tcp->dst_port, tcp->src_port, TRANSPORT_PROTO_TCP, - thread_index); + thread_index, &is_filtered); tc = tcp_get_connection_from_transport (tconn); ASSERT (tcp_lookup_is_valid (tc, tcp)); } @@ -1928,7 +1929,7 @@ tcp_lookup_connection (u32 fib_index, vlib_buffer_t * b, u8 thread_index, tcp->dst_port, tcp->src_port, TRANSPORT_PROTO_TCP, - thread_index); + thread_index, &is_filtered); tc = tcp_get_connection_from_transport (tconn); ASSERT (tcp_lookup_is_valid (tc, tcp)); } @@ -2939,7 +2940,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, ip4_header_t *ip40; ip6_header_t *ip60; u32 error0 = TCP_ERROR_NO_LISTENER, next0 = TCP_INPUT_NEXT_DROP; - u8 flags0; + u8 flags0, is_filtered = 0; bi0 = from[0]; to_next[0] = bi0; @@ -2968,9 +2969,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, tcp0->dst_port, tcp0->src_port, TRANSPORT_PROTO_TCP, - my_thread_index); - tc0 = tcp_get_connection_from_transport (tconn); - ASSERT (tcp_lookup_is_valid (tc0, tcp0)); + my_thread_index, + &is_filtered); } else { @@ -2986,9 +2986,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, tcp0->dst_port, tcp0->src_port, TRANSPORT_PROTO_TCP, - my_thread_index); - tc0 = tcp_get_connection_from_transport (tconn); - ASSERT (tcp_lookup_is_valid (tc0, tcp0)); + my_thread_index, + &is_filtered); } /* Length check */ @@ -2999,8 +2998,11 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } /* Session exists */ - if (PREDICT_TRUE (0 != tc0)) + if (PREDICT_TRUE (0 != tconn)) { + tc0 = tcp_get_connection_from_transport (tconn); + ASSERT (tcp_lookup_is_valid (tc0, tcp0)); + /* Save connection index */ vnet_buffer (b0)->tcp.connection_index = tc0->c_c_index; vnet_buffer (b0)->tcp.seq_number = @@ -3032,8 +3034,13 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - if ((is_ip4 && tm->punt_unknown4) || - (!is_ip4 && tm->punt_unknown6)) + if (is_filtered) + { + next0 = TCP_INPUT_NEXT_DROP; + error0 = TCP_ERROR_FILTERED; + } + else if ((is_ip4 && tm->punt_unknown4) || + (!is_ip4 && tm->punt_unknown6)) { next0 = TCP_INPUT_NEXT_PUNT; error0 = TCP_ERROR_PUNT; @@ -3044,6 +3051,7 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, next0 = TCP_INPUT_NEXT_RESET; error0 = TCP_ERROR_NO_LISTENER; } + tc0 = 0; } done: @@ -3051,8 +3059,8 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - tcp_rx_trace_t *t0 = - vlib_add_trace (vm, node, b0, sizeof (*t0)); + tcp_rx_trace_t *t0; + t0 = vlib_add_trace (vm, node, b0, sizeof (*t0)); tcp_set_rx_trace_data (t0, tc0, tcp0, b0, is_ip4); } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, diff --git a/src/vnet/tcp/tcp_test.c b/src/vnet/tcp/tcp_test.c index 021f416cb76..e3cdb1be758 100644 --- a/src/vnet/tcp/tcp_test.c +++ b/src/vnet/tcp/tcp_test.c @@ -1558,7 +1558,7 @@ tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input) transport_connection_t _tc1, *tc1 = &_tc1, _tc2, *tc2 = &_tc2, *tconn; tcp_connection_t *tc; stream_session_t *s; - u8 cmp = 0; + u8 cmp = 0, is_filtered = 0; pool_get (smm->sessions[0], s); memset (s, 0, sizeof (*s)); @@ -1601,7 +1601,7 @@ tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input) tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4, &tc1->rmt_ip.ip4, tc1->lcl_port, tc1->rmt_port, - tc1->proto, 0); + tc1->proto, 0, &is_filtered); cmp = (memcmp (&tconn->rmt_ip, &tc1->rmt_ip, sizeof (tc1->rmt_ip)) == 0); TCP_TEST ((cmp), "rmt ip is identical %d", cmp); TCP_TEST ((tconn->lcl_port == tc1->lcl_port), @@ -1614,7 +1614,7 @@ tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input) tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4, &tc2->rmt_ip.ip4, tc2->lcl_port, tc2->rmt_port, - tc2->proto, 0); + tc2->proto, 0, &is_filtered); TCP_TEST ((tconn == 0), "lookup result should be null"); /* @@ -1624,12 +1624,12 @@ tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input) tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4, &tc1->rmt_ip.ip4, tc1->lcl_port, tc1->rmt_port, - tc1->proto, 0); + tc1->proto, 0, &is_filtered); TCP_TEST ((tconn == 0), "lookup result should be null"); tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4, &tc2->rmt_ip.ip4, tc2->lcl_port, tc2->rmt_port, - tc2->proto, 0); + tc2->proto, 0, &is_filtered); TCP_TEST ((tconn == 0), "lookup result should be null"); /* @@ -1639,7 +1639,7 @@ tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input) tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4, &tc2->rmt_ip.ip4, tc2->lcl_port, tc2->rmt_port, - tc2->proto, 0); + tc2->proto, 0, &is_filtered); TCP_TEST ((tconn == 0), "lookup result should be null"); return 0; -- cgit 1.2.3-korg