API refactoring : vhost_user
[vpp.git] / vnet / vnet / bfd / bfd_udp.c
index ded3342..3c747d8 100644 (file)
@@ -26,6 +26,9 @@ typedef struct
   mhash_t bfd_session_idx_by_bfd_key;
 } bfd_udp_main_t;
 
+static vlib_node_registration_t bfd_udp4_input_node;
+static vlib_node_registration_t bfd_udp6_input_node;
+
 bfd_udp_main_t bfd_udp_main;
 
 void bfd_udp_transport_to_buffer (vlib_main_t *vm, vlib_buffer_t *b,
@@ -311,7 +314,23 @@ typedef enum {
 static void bfd_udp4_find_headers (vlib_buffer_t *b, const ip4_header_t **ip4,
                                    const udp_header_t **udp)
 {
-  *ip4 = vnet_buffer (b)->ip.header;
+  /* sanity check first */
+  const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+  if (start < 0 && start < sizeof (b->pre_data))
+    {
+      BFD_ERR ("Start of ip header is before pre_data, ignoring");
+      *ip4 = NULL;
+      *udp = NULL;
+      return;
+    }
+  *ip4 = (ip4_header_t *)(b->data + start);
+  if ((u8 *)*ip4 > (u8 *)vlib_buffer_get_current (b))
+    {
+      BFD_ERR ("Start of ip header is beyond current data, ignoring");
+      *ip4 = NULL;
+      *udp = NULL;
+      return;
+    }
   *udp = (udp_header_t *)((*ip4) + 1);
 }
 
@@ -423,7 +442,7 @@ static bfd_udp_error_t bfd_udp4_scan (vlib_main_t *vm, vlib_node_runtime_t *rt,
       BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
       return BFD_UDP_ERROR_BAD;
     }
-  BFD_DBG ("BFD session found, bs_idx=%d", bs->bs_idx);
+  BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
   if (!bfd_verify_pkt_session (pkt, b->current_length, bs))
     {
       return BFD_UDP_ERROR_BAD;
@@ -493,14 +512,24 @@ static uword bfd_udp_input (vlib_main_t *vm, vlib_node_runtime_t *rt,
       next0 = BFD_UDP_INPUT_NEXT_NORMAL;
       if (BFD_UDP_ERROR_NONE == error0)
         {
-         /* if everything went fine, check for poll bit, if present, re-use
-            the buffer and based on (now update) session parameters, send the
-            final packet back */
+          /* if everything went fine, check for poll bit, if present, re-use
+             the buffer and based on (now updated) session parameters, send the
+             final packet back */
           const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
           if (bfd_pkt_get_poll (pkt))
             {
               bfd_send_final (vm, b0, bs);
-             next0 = BFD_UDP_INPUT_NEXT_REPLY;
+              if (is_ipv6)
+                {
+                  vlib_node_increment_counter (vm, bfd_udp6_input_node.index,
+                                               b0->error, 1);
+                }
+              else
+                {
+                  vlib_node_increment_counter (vm, bfd_udp4_input_node.index,
+                                               b0->error, 1);
+                }
+              next0 = BFD_UDP_INPUT_NEXT_REPLY;
             }
         }
       vlib_set_next_frame_buffer (vm, rt, next0, bi0);