aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ethernet/arp.c
diff options
context:
space:
mode:
authorMatthew Smith <mgsmith@netgate.com>2017-05-16 21:35:56 -0500
committerDamjan Marion <dmarion.lists@gmail.com>2017-05-17 13:43:17 +0000
commitcb9ab47fd388c237fe0bad53d07e99096d338ac8 (patch)
treeae6af784f244d5de51ea62eb85e4077aaf631dc0 /src/vnet/ethernet/arp.c
parent025d4151e2d7627aa771d577d405464a276039ad (diff)
VPP-719: Accept ARP replies from VRRP hw addr
Check whether an ARP src hw addr starts with 00:00:5e:00:01 before rejecting due to a mismatch between ARP src hw addr and ethernet frame src addr. Change-Id: Ia3ecd5d6dba34876aca8d90bc622a0a1397e48fb Signed-off-by: Matthew Smith <mgsmith@netgate.com>
Diffstat (limited to 'src/vnet/ethernet/arp.c')
-rw-r--r--src/vnet/ethernet/arp.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c
index bfcd3573..f44cb594 100644
--- a/src/vnet/ethernet/arp.c
+++ b/src/vnet/ethernet/arp.c
@@ -107,6 +107,8 @@ typedef struct
#define ETHERNET_ARP_ARGS_POPULATE (1<<2)
} vnet_arp_set_ip4_over_ethernet_rpc_args_t;
+static const u8 vrrp_prefix[] = { 0x00, 0x00, 0x5E, 0x00, 0x01 };
+
static void
set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
* a);
@@ -991,7 +993,7 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
ethernet_header_t *eth0;
ip4_address_t *if_addr0, proxy_src;
u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
- u8 is_request0, dst_is_local0, is_unnum0;
+ u8 is_request0, dst_is_local0, is_unnum0, is_vrrp_reply0;
ethernet_proxy_arp_t *pa;
fib_node_index_t dst_fei, src_fei;
fib_prefix_t pfx0;
@@ -1097,10 +1099,19 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
/* Fill in ethernet header. */
eth0 = ethernet_buffer_get_header (p0);
+ is_vrrp_reply0 =
+ ((arp0->opcode ==
+ clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply))
+ &&
+ (!memcmp
+ (arp0->ip4_over_ethernet[0].ethernet, vrrp_prefix,
+ sizeof (vrrp_prefix))));
+
/* Trash ARP packets whose ARP-level source addresses do not
- match their L2-frame-level source addresses */
+ match their L2-frame-level source addresses, unless it's
+ a reply from a VRRP virtual router */
if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
- sizeof (eth0->src_address)))
+ sizeof (eth0->src_address)) && !is_vrrp_reply0)
{
error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
goto drop2;
@@ -2170,6 +2181,7 @@ arp_term_l2bd (vlib_main_t * vm,
u16 bd_index0;
u32 ip0;
u8 *macp0;
+ u8 is_vrrp_reply0;
pi0 = from[0];
to_next[0] = pi0;
@@ -2218,12 +2230,20 @@ arp_term_l2bd (vlib_main_t * vm,
if (error0)
goto drop;
+ is_vrrp_reply0 =
+ ((arp0->opcode ==
+ clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply))
+ &&
+ (!memcmp
+ (arp0->ip4_over_ethernet[0].ethernet, vrrp_prefix,
+ sizeof (vrrp_prefix))));
+
/* Trash ARP packets whose ARP-level source addresses do not
- match their L2-frame-level source addresses */
+ match their L2-frame-level source addresses, unless it's
+ a reply from a VRRP virtual router */
if (PREDICT_FALSE
- (memcmp
- (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
- sizeof (eth0->src_address))))
+ (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
+ sizeof (eth0->src_address)) && !is_vrrp_reply0))
{
error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
goto drop;