aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWojciech Dec <wdec@cisco.com>2016-10-20 11:25:37 +0200
committerOle Trøan <otroan@employees.org>2016-11-04 13:12:37 +0000
commit96e6f958bbac88e04ef6fd04bc0abda22a3b37bc (patch)
tree5ec66a1f75f60059390a1366bd9a9cb0193f11f9
parente21c52861d7c503bef7fc464f23bbc7891e150d7 (diff)
DHCPv6: relay reply fixes (VPP-510)
Fixes DHCPv6 relay reply message corruption. Change-Id: Iead995f29d2fa9cbb04f0f9d42b3aa9002267117 Signed-off-by: Wojciech Dec <wdec@cisco.com>
-rw-r--r--vnet/vnet/dhcpv6/proxy_error.def1
-rw-r--r--vnet/vnet/dhcpv6/proxy_node.c49
2 files changed, 36 insertions, 14 deletions
diff --git a/vnet/vnet/dhcpv6/proxy_error.def b/vnet/vnet/dhcpv6/proxy_error.def
index ffa1d68dda4..062e97aa4c2 100644
--- a/vnet/vnet/dhcpv6/proxy_error.def
+++ b/vnet/vnet/dhcpv6/proxy_error.def
@@ -23,5 +23,6 @@ dhcpv6_proxy_error (NO_INTERFACE_ADDRESS, "DHCPV6 no interface address")
dhcpv6_proxy_error (WRONG_MESSAGE_TYPE, "DHCPV6 wrong message type.")
dhcpv6_proxy_error (NO_SRC_ADDRESS, "DHCPV6 no srouce IPv6 address configured.")
dhcpv6_proxy_error (NO_CIRCUIT_ID_OPTION, "DHCPv6 reply packets without circuit ID option")
+dhcpv6_proxy_error (NO_RELAY_MESSAGE_OPTION, "DHCPv6 reply packets without relay message option")
dhcpv6_proxy_error (BAD_SVR_FIB_OR_ADDRESS, "DHCPv6 packets not from DHCPv6 server or server FIB.")
dhcpv6_proxy_error (PKT_TOO_BIG, "DHCPv6 packets which are too big.")
diff --git a/vnet/vnet/dhcpv6/proxy_node.c b/vnet/vnet/dhcpv6/proxy_node.c
index 323bdf9b730..e44cd3f8956 100644
--- a/vnet/vnet/dhcpv6/proxy_node.c
+++ b/vnet/vnet/dhcpv6/proxy_node.c
@@ -511,8 +511,10 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm,
vnet_sw_interface_t *si0;
u32 error0 = (u32)~0;
vnet_sw_interface_t *swif;
- dhcpv6_option_t *r0, *o;
+ dhcpv6_option_t *r0 = 0, *o;
u16 len = 0;
+ u8 interface_opt_flag = 0;
+ u8 relay_msg_opt_flag = 0;
u32 svr_fib_index, svr_fib_id;
ip6_fib_t * svr_fib;
ip6_main_t * im = &ip6_main;
@@ -520,7 +522,7 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm,
bi0 = from[0];
from += 1;
n_left_from -= 1;
-
+
b0 = vlib_get_buffer (vm, bi0);
h0 = vlib_buffer_get_current (b0);
@@ -547,31 +549,50 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm,
}
u0 = (void *)h0 -(sizeof(*u0));
ip0 = (void *)u0 -(sizeof(*ip0));
-
+
vlib_buffer_advance (b0, sizeof(*h0));
- o = r0 = vlib_buffer_get_current (b0);
-
- /* Parse through TLVs looking for option 9 (DHCPV6_OPTION_INTERFACE_ID).
+ o = vlib_buffer_get_current (b0);
+
+ /* Parse through TLVs looking for option 18 (DHCPV6_OPTION_INTERFACE_ID)
+ _and_ option 9 (DHCPV6_OPTION_RELAY_MSG) option which must be there.
+ Currently assuming no other options need to be processed
The interface-ID is the FIB number we need
to track down the client-facing interface */
-
+
while ((u8 *) o < (b0->data + b0->current_data + b0->current_length))
{
if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16(o->option))
{
+ interface_opt_flag = 1;
if (clib_net_to_host_u16(o->length) == sizeof(sw_if_index))
sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
- break;
- }
+ }
+ if (DHCPV6_OPTION_RELAY_MSG == clib_net_to_host_u16(o->option))
+ {
+ relay_msg_opt_flag = 1;
+ r0 = vlib_buffer_get_current (b0);
+ }
+ if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1))
+ break;
+ vlib_buffer_advance (b0, sizeof(*o) + clib_net_to_host_u16(o->length));
o = (dhcpv6_option_t *) (((uword) o) + clib_net_to_host_u16(o->length) + sizeof(*o));
}
-
+
+ if ((relay_msg_opt_flag == 0) || (r0 == 0))
+ {
+ error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION;
+ goto drop_packet;
+ }
+
if ((u32)~0 == sw_if_index)
{
error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
goto drop_packet;
}
+ //Advance buffer to start of encapsulated DHCPv6 message
+ vlib_buffer_advance (b0, sizeof(*r0));
+
svr_fib_index = im->fib_index_by_sw_if_index
[vnet_buffer(b0)->sw_if_index[VLIB_RX]];
svr_fib = ip6_fib_get (svr_fib_index);
@@ -586,16 +607,16 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm,
goto drop_packet;
}
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = original_sw_if_index
= sw_if_index;
swif = vnet_get_sw_interface (vnm, original_sw_if_index);
if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
sw_if_index = swif->unnumbered_sw_if_index;
- vlib_buffer_advance (b0, sizeof(*r0));
- /*
- * udp_local hands us the DHCPV6 header, need udp hdr,
+
+ /*
+ * udp_local hands us the DHCPV6 header, need udp hdr,
* ip hdr to relay to client
*/
vlib_buffer_advance (b0, -(sizeof(*u1)));