aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Pfister <ppfister@cisco.com>2016-06-22 12:58:30 +0100
committerChris Luke <chris_luke@cable.comcast.com>2016-06-22 17:09:33 +0000
commitd076f19b5e119265d995a031707c8d78608c439f (patch)
treeed5c48a979a26534da3b6228b5f71ae5e506c84a
parent5b7a563ff0a39b74a0f037572b7709e3c9aa5cf2 (diff)
ARP/NDP does not send solicitation when no source address is available
Currently, when the interface has no address assigned to it, VPP crashes as ip_interface_address_for_packet assumes there always is at least one address. This patch checks if an address is available at all. The only part of VPP using it is ARP or NDP. When a neighbor discovery message has to be sent while there is no address assigned on the interace, no solicitation is sent and an error counter is incremented. Change-Id: Ia9fdaf8e84050a1ceeb47f5370819d3df95714f0 Signed-off-by: Pierre Pfister <ppfister@cisco.com>
-rw-r--r--vnet/vnet/ethernet/arp_packet.h3
-rw-r--r--vnet/vnet/ip/ip4.h5
-rw-r--r--vnet/vnet/ip/ip4_forward.c8
-rw-r--r--vnet/vnet/ip/ip6.h5
-rw-r--r--vnet/vnet/ip/ip6_forward.c12
-rw-r--r--vnet/vnet/ip/lookup.h2
6 files changed, 28 insertions, 7 deletions
diff --git a/vnet/vnet/ethernet/arp_packet.h b/vnet/vnet/ethernet/arp_packet.h
index c2214949d89..b3447c5e1c1 100644
--- a/vnet/vnet/ethernet/arp_packet.h
+++ b/vnet/vnet/ethernet/arp_packet.h
@@ -109,7 +109,8 @@ typedef enum {
IP4_ARP_ERROR_REQUEST_SENT,
IP4_ARP_ERROR_NON_ARP_ADJ,
IP4_ARP_ERROR_REPLICATE_DROP,
- IP4_ARP_ERROR_REPLICATE_FAIL
+ IP4_ARP_ERROR_REPLICATE_FAIL,
+ IP4_ARP_ERROR_NO_SOURCE_ADDRESS,
} ip4_arp_error_t;
typedef CLIB_PACKED (struct {
diff --git a/vnet/vnet/ip/ip4.h b/vnet/vnet/ip/ip4.h
index c01006ea590..f005522bb7a 100644
--- a/vnet/vnet/ip/ip4.h
+++ b/vnet/vnet/ip/ip4.h
@@ -237,13 +237,16 @@ ip4_unaligned_destination_matches_route (ip4_main_t * im,
uword dest_length)
{ return 0 == ((clib_mem_unaligned (&key->data_u32, u32) ^ dest->data_u32) & im->fib_masks[dest_length]); }
-always_inline void
+always_inline int
ip4_src_address_for_packet (ip4_main_t * im, vlib_buffer_t * p, ip4_address_t * src, u32 sw_if_index)
{
ip_lookup_main_t * lm = &im->lookup_main;
ip_interface_address_t * ia = ip_interface_address_for_packet (lm, p, sw_if_index);
+ if (ia == NULL)
+ return -1;
ip4_address_t * a = ip_interface_address_get_address (lm, ia);
*src = a[0];
+ return 0;
}
/* Find interface address which matches destination. */
diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c
index 3075e0c3f73..08a1785aaa5 100644
--- a/vnet/vnet/ip/ip4_forward.c
+++ b/vnet/vnet/ip/ip4_forward.c
@@ -2373,7 +2373,12 @@ ip4_arp (vlib_main_t * vm,
clib_memcpy (h0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address,
sizeof (h0->ip4_over_ethernet[0].ethernet));
- ip4_src_address_for_packet (im, p0, &h0->ip4_over_ethernet[0].ip4, sw_if_index0);
+ if (ip4_src_address_for_packet (im, p0, &h0->ip4_over_ethernet[0].ip4, sw_if_index0)) {
+ //No source address available
+ p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
+ vlib_buffer_free(vm, &bi0, 1);
+ continue;
+ }
/* Copy in destination address we are requesting. */
h0->ip4_over_ethernet[1].ip4.data_u32 = ip0->dst_address.data_u32;
@@ -2400,6 +2405,7 @@ static char * ip4_arp_error_strings[] = {
[IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
[IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
[IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
+ [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
};
VLIB_REGISTER_NODE (ip4_arp_node) = {
diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h
index 312e39845b4..70e32672530 100644
--- a/vnet/vnet/ip/ip6.h
+++ b/vnet/vnet/ip/ip6.h
@@ -289,13 +289,16 @@ ip6_unaligned_destination_matches_route (ip6_main_t * im,
return 1;
}
-always_inline void
+always_inline int
ip6_src_address_for_packet (ip6_main_t * im, vlib_buffer_t * p, ip6_address_t * src, u32 sw_if_index)
{
ip_lookup_main_t * lm = &im->lookup_main;
ip_interface_address_t * ia = ip_interface_address_for_packet (lm, p, sw_if_index);
+ if (ia == NULL)
+ return -1;
ip6_address_t * a = ip_interface_address_get_address (lm, ia);
*src = a[0];
+ return 0;
}
always_inline u32
diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c
index 86ee8d5ba2b..b558787c45c 100644
--- a/vnet/vnet/ip/ip6_forward.c
+++ b/vnet/vnet/ip/ip6_forward.c
@@ -1993,6 +1993,7 @@ typedef enum {
typedef enum {
IP6_DISCOVER_NEIGHBOR_ERROR_DROP,
IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT,
+ IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS,
} ip6_discover_neighbor_error_t;
static uword
@@ -2123,8 +2124,13 @@ ip6_discover_neighbor (vlib_main_t * vm,
* Choose source address based on destination lookup
* adjacency.
*/
- ip6_src_address_for_packet (im, p0, &h0->ip.src_address,
- sw_if_index0);
+ if (ip6_src_address_for_packet (im, p0, &h0->ip.src_address,
+ sw_if_index0)) {
+ //There is no address on the interface
+ p0->error = node->errors[IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS];
+ vlib_buffer_free(vm, &bi0, 1);
+ continue;
+ }
/*
* Destination address is a solicited node multicast address.
@@ -2175,6 +2181,8 @@ static char * ip6_discover_neighbor_error_strings[] = {
[IP6_DISCOVER_NEIGHBOR_ERROR_DROP] = "address overflow drops",
[IP6_DISCOVER_NEIGHBOR_ERROR_REQUEST_SENT]
= "neighbor solicitations sent",
+ [IP6_DISCOVER_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS]
+ = "no source address for ND solicitation",
};
VLIB_REGISTER_NODE (ip6_discover_neighbor_node) = {
diff --git a/vnet/vnet/ip/lookup.h b/vnet/vnet/ip/lookup.h
index 35c19a77327..c22c5003fd3 100644
--- a/vnet/vnet/ip/lookup.h
+++ b/vnet/vnet/ip/lookup.h
@@ -531,7 +531,7 @@ ip_interface_address_for_packet (ip_lookup_main_t * lm, vlib_buffer_t * b, u32 s
vec_elt (lm->if_address_pool_index_by_sw_if_index, sw_if_index)
: if_address_index);
- return pool_elt_at_index (lm->if_address_pool, if_address_index);
+ return (if_address_index != ~0)?pool_elt_at_index (lm->if_address_pool, if_address_index):NULL;
}
#define foreach_ip_interface_address(lm,a,sw_if_index,loop,body) \