Commit 93a3661c authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka
Browse files

Flowspec: split net_format_flowspec into several functions

parent 2af807a8
Loading
Loading
Loading
Loading
+147 −121
Original line number Diff line number Diff line
@@ -929,21 +929,6 @@ get_value(const byte *val, u8 len)
  return 0;
}

static int
is_bitmask(enum flow_type type)
{
  switch (type)
  {
  case FLOW_TYPE_TCP_FLAGS:
  case FLOW_TYPE_FRAGMENT:
  case FLOW_TYPE_LABEL:
    return 1;

  default:
    return 0;
  }
}

static const char *
fragment_val_str(u8 val)
{
@@ -957,59 +942,26 @@ fragment_val_str(u8 val)
  return "???";
}

static uint
net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
{
  buffer b = {
    .start = buf,
    .pos = buf,
    .end = buf + blen,
  };

  const byte *part = flow_first_part(data);
  *buf = 0;

  if (ipv6)
    buffer_puts(&b, "flow6 { ");
  else
    buffer_puts(&b, "flow4 { ");

  while (part)
  {
    buffer_print(&b, "%s ", flow_type_str(*part, ipv6));

    switch (*part)
    {
    case FLOW_TYPE_DST_PREFIX:
    case FLOW_TYPE_SRC_PREFIX:
static void
net_format_flow_ip(buffer *b, const byte *part, int ipv6)
{
  uint pxlen = *(part+1);
  if (ipv6)
  {
    uint pxoffset = *(part+2);
    if (pxoffset)
	  buffer_print(&b, "%I6/%u offset %u; ", flow_read_ip6(part+3,pxlen,pxoffset), pxlen, pxoffset);
      buffer_print(b, "%I6/%u offset %u; ", flow_read_ip6(part+3,pxlen,pxoffset), pxlen, pxoffset);
    else
	  buffer_print(&b, "%I6/%u; ", flow_read_ip6(part+3,pxlen,0), pxlen);
      buffer_print(b, "%I6/%u; ", flow_read_ip6(part+3,pxlen,0), pxlen);
  }
  else
  {
	buffer_print(&b, "%I4/%u; ", flow_read_ip4(part+2,pxlen), pxlen);
    buffer_print(b, "%I4/%u; ", flow_read_ip4(part+2,pxlen), pxlen);
  }
      break;
}

    case FLOW_TYPE_IP_PROTOCOL: /* == FLOW_TYPE_NEXT_HEADER */
    case FLOW_TYPE_PORT:
    case FLOW_TYPE_DST_PORT:
    case FLOW_TYPE_SRC_PORT:
    case FLOW_TYPE_ICMP_TYPE:
    case FLOW_TYPE_ICMP_CODE:
    case FLOW_TYPE_TCP_FLAGS:
    case FLOW_TYPE_PACKET_LENGTH:
    case FLOW_TYPE_DSCP:
    case FLOW_TYPE_FRAGMENT:
    case FLOW_TYPE_LABEL:
static void
net_format_flow_num(buffer *b, const byte *part)
{
  const byte *last_op = NULL;
  const byte *op = part+1;
@@ -1022,21 +974,16 @@ net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
    if (!first)
    {
      /* XXX: I don't like this so complicated if-tree */
	  if (!isset_and(op) && !is_bitmask(*part) &&
      if (!isset_and(op) &&
	  ((num_op(     op) == FLOW_EQ) || (num_op(     op) == FLOW_GTE)) &&
	  ((num_op(last_op) == FLOW_EQ) || (num_op(last_op) == FLOW_LTE)))
      {
	    b.pos--; /* Remove last char (it is a space) */
	    buffer_puts(&b, ",");
	  }
	  else if (isset_and(op) && is_bitmask(*part))
	  {
	    b.pos--; /* Remove last char (it is a space) */
	    buffer_puts(&b, ",");
	b->pos--; /* Remove last char (it is a space) */
	buffer_puts(b, ",");
      }
      else
      {
	    buffer_puts(&b, isset_and(op) ? "&& " : "|| ");
	buffer_puts(b, isset_and(op) ? "&& " : "|| ");
      }
    }
    first = 0;
@@ -1044,61 +991,140 @@ net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
    len = get_value_length(op);
    val = get_value(op+1, len);

	if (is_bitmask(*part))
	{
	  /*
	   *   Not Match  Show
	   *  ------------------
	   *    0    0    !0/B
	   *    0    1     B/B
	   *    1    0     0/B
	   *    1    1    !B/B
	   */

	  if ((*op & 0x3) == 0x3 || (*op & 0x3) == 0)
	    buffer_puts(&b, "!");

	  if (*part == FLOW_TYPE_FRAGMENT && (val == 1 || val == 2 || val == 4 || val == 8))
	    buffer_print(&b, "%s%s", ((*op & 0x1) ? "" : "!"), fragment_val_str(val));
	  else
	    buffer_print(&b, "0x%x/0x%x", ((*op & 0x1) ? val : 0), val);
	}
	else
	{
    if (!isset_end(op) && !isset_and(op) && isset_and(op+1+len) &&
	(num_op(op) == FLOW_GTE) && (num_op(op+1+len) == FLOW_LTE))
    {
      /* Display interval */
	    buffer_print(&b, "%u..", val);
      buffer_print(b, "%u..", val);
      op += 1 + len;
      len = get_value_length(op);
      val = get_value(op+1, len);
	    buffer_print(&b, "%u", val);
      buffer_print(b, "%u", val);
    }
    else if (num_op(op) == FLOW_EQ)
    {
	    buffer_print(&b, "%u", val);
      buffer_print(b, "%u", val);
    }
    else
    {
	    buffer_print(&b, "%s %u", num_op_str(op), val);
	  }
      buffer_print(b, "%s %u", num_op_str(op), val);
    }

    if (isset_end(op))
    {
	  buffer_puts(&b, "; ");
      buffer_puts(b, "; ");
      break;
    }
    else
    {
	  buffer_puts(&b, " ");
      buffer_puts(b, " ");
    }

    last_op = op;
    op += 1 + len;
  }
}

static void
net_format_flow_bitmask(buffer *b, const byte *part)
{
  const byte *op = part+1;
  u64 val;
  uint len;
  uint first = 1;

  while (1)
  {
    if (!first)
    {
      if (isset_and(op))
      {
	b->pos--; /* Remove last char (it is a space) */
	buffer_puts(b, ",");
      }
      else
      {
	buffer_puts(b, "|| ");
      }
    }
    first = 0;

    len = get_value_length(op);
    val = get_value(op+1, len);

    /*
     *   Not Match  Show
     *  ------------------
     *    0    0    !0/B
     *    0    1     B/B
     *    1    0     0/B
     *    1    1    !B/B
     */

    if ((*op & 0x3) == 0x3 || (*op & 0x3) == 0)
      buffer_puts(b, "!");

    if (*part == FLOW_TYPE_FRAGMENT && (val == 1 || val == 2 || val == 4 || val == 8))
      buffer_print(b, "%s%s", ((*op & 0x1) ? "" : "!"), fragment_val_str(val));
    else
      buffer_print(b, "0x%x/0x%x", ((*op & 0x1) ? val : 0), val);

    if (isset_end(op))
    {
      buffer_puts(b, "; ");
      break;
    }
    else
    {
      buffer_puts(b, " ");
    }

    op += 1 + len;
  }
}

static uint
net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
{
  buffer b = {
    .start = buf,
    .pos = buf,
    .end = buf + blen,
  };

  const byte *part = flow_first_part(data);
  *buf = 0;

  if (ipv6)
    buffer_puts(&b, "flow6 { ");
  else
    buffer_puts(&b, "flow4 { ");

  while (part)
  {
    buffer_print(&b, "%s ", flow_type_str(*part, ipv6));

    switch (*part)
    {
    case FLOW_TYPE_DST_PREFIX:
    case FLOW_TYPE_SRC_PREFIX:
      net_format_flow_ip(&b, part, ipv6);
      break;
    case FLOW_TYPE_IP_PROTOCOL: /* == FLOW_TYPE_NEXT_HEADER */
    case FLOW_TYPE_PORT:
    case FLOW_TYPE_DST_PORT:
    case FLOW_TYPE_SRC_PORT:
    case FLOW_TYPE_ICMP_TYPE:
    case FLOW_TYPE_ICMP_CODE:
    case FLOW_TYPE_PACKET_LENGTH:
    case FLOW_TYPE_DSCP:
      net_format_flow_num(&b, part);
      break;
    case FLOW_TYPE_TCP_FLAGS:
    case FLOW_TYPE_FRAGMENT:
    case FLOW_TYPE_LABEL:
      net_format_flow_bitmask(&b, part);
      break;
    }

    part = flow_next_part(part, data+dlen, ipv6);