vom: Add support for redirect contracts in gbp
[vpp.git] / src / plugins / cdp / cdp_input.c
index bce8eeb..a27113d 100644 (file)
@@ -93,8 +93,11 @@ format_text_tlv (u8 * s, va_list * va)
 
   s = format (s, "%s(%d): ", h->name, t->t);
 
-  for (i = 0; i < (t->l - sizeof (*t)); i++)
-    vec_add1 (s, t->v[i]);
+  if (t->l >= 4)
+    {
+      for (i = 0; i < (t->l - sizeof (*t)); i++)
+       vec_add1 (s, t->v[i]);
+    }
 
   vec_add1 (s, '\n');
   return s;
@@ -250,7 +253,7 @@ process_cdp_hdr (cdp_main_t * cm, cdp_neighbor_t * n, cdp_hdr_t * h)
 static int
 cdp_packet_scan (cdp_main_t * cm, cdp_neighbor_t * n)
 {
-  u8 *cur = n->last_rx_pkt;
+  u8 *end, *cur = n->last_rx_pkt;
   cdp_hdr_t *h;
   cdp_tlv_t *tlv;
   cdp_error_t e = CDP_ERROR_NONE;
@@ -269,13 +272,29 @@ cdp_packet_scan (cdp_main_t * cm, cdp_neighbor_t * n)
   if (e)
     return e;
 
+  // there are no tlvs
+  if (vec_len (n->last_rx_pkt) <= 0)
+    return CDP_ERROR_BAD_TLV;
+
   cur = (u8 *) (h + 1);
+  end = n->last_rx_pkt + vec_len (n->last_rx_pkt) - 1;
 
-  while (cur < n->last_rx_pkt + vec_len (n->last_rx_pkt) - 1)
+  // look ahead 4 bytes (u16 tlv->t + u16 tlv->l)
+  while (cur + 3 <= end)
     {
       tlv = (cdp_tlv_t *) cur;
       tlv->t = ntohs (tlv->t);
       tlv->l = ntohs (tlv->l);
+
+      /* tlv length includes t, l and v */
+
+      if (tlv->l < 4)
+       return CDP_ERROR_BAD_TLV;
+
+      cur += tlv->l;
+      if ((cur - 1) > end)
+       return CDP_ERROR_BAD_TLV;
+
       /*
        * Only process known TLVs. In practice, certain
        * devices send tlv->t = 0xFF, perhaps as an EOF of sorts.
@@ -288,10 +307,12 @@ cdp_packet_scan (cdp_main_t * cm, cdp_neighbor_t * n)
          if (e)
            return e;
        }
-      /* tlv length includes (t, l) */
-      cur += tlv->l;
     }
 
+  // did not process all tlvs or none tlv processed
+  if ((cur - 1) != end)
+    return CDP_ERROR_BAD_TLV;
+
   return CDP_ERROR_NONE;
 }
 
@@ -315,7 +336,7 @@ cdp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0)
   if (p == 0)
     {
       pool_get (cm->neighbors, n);
-      memset (n, 0, sizeof (*n));
+      clib_memset (n, 0, sizeof (*n));
       n->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
       n->packet_template_index = (u8) ~ 0;
       hash_set (cm->neighbor_by_sw_if_index, n->sw_if_index,