0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Flowspec: split net_format_flowspec into several functions

This commit is contained in:
Jan Moskyto Matejka 2017-04-26 12:26:14 +02:00
parent 2af807a83f
commit 93a3661c15

View File

@ -929,21 +929,6 @@ get_value(const byte *val, u8 len)
return 0; 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 * static const char *
fragment_val_str(u8 val) fragment_val_str(u8 val)
{ {
@ -957,6 +942,147 @@ fragment_val_str(u8 val)
return "???"; return "???";
} }
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);
else
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);
}
}
static void
net_format_flow_num(buffer *b, const byte *part)
{
const byte *last_op = NULL;
const byte *op = part+1;
u64 val;
uint len;
uint first = 1;
while (1)
{
if (!first)
{
/* XXX: I don't like this so complicated if-tree */
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
{
buffer_puts(b, isset_and(op) ? "&& " : "|| ");
}
}
first = 0;
len = get_value_length(op);
val = get_value(op+1, len);
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);
op += 1 + len;
len = get_value_length(op);
val = get_value(op+1, len);
buffer_print(b, "%u", val);
}
else if (num_op(op) == FLOW_EQ)
{
buffer_print(b, "%u", val);
}
else
{
buffer_print(b, "%s %u", num_op_str(op), val);
}
if (isset_end(op))
{
buffer_puts(b, "; ");
break;
}
else
{
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 static uint
net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6) net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
{ {
@ -982,123 +1108,23 @@ net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
{ {
case FLOW_TYPE_DST_PREFIX: case FLOW_TYPE_DST_PREFIX:
case FLOW_TYPE_SRC_PREFIX: case FLOW_TYPE_SRC_PREFIX:
{ net_format_flow_ip(&b, part, 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);
else
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);
}
break; break;
}
case FLOW_TYPE_IP_PROTOCOL: /* == FLOW_TYPE_NEXT_HEADER */ case FLOW_TYPE_IP_PROTOCOL: /* == FLOW_TYPE_NEXT_HEADER */
case FLOW_TYPE_PORT: case FLOW_TYPE_PORT:
case FLOW_TYPE_DST_PORT: case FLOW_TYPE_DST_PORT:
case FLOW_TYPE_SRC_PORT: case FLOW_TYPE_SRC_PORT:
case FLOW_TYPE_ICMP_TYPE: case FLOW_TYPE_ICMP_TYPE:
case FLOW_TYPE_ICMP_CODE: case FLOW_TYPE_ICMP_CODE:
case FLOW_TYPE_TCP_FLAGS:
case FLOW_TYPE_PACKET_LENGTH: case FLOW_TYPE_PACKET_LENGTH:
case FLOW_TYPE_DSCP: case FLOW_TYPE_DSCP:
net_format_flow_num(&b, part);
break;
case FLOW_TYPE_TCP_FLAGS:
case FLOW_TYPE_FRAGMENT: case FLOW_TYPE_FRAGMENT:
case FLOW_TYPE_LABEL: case FLOW_TYPE_LABEL:
{ net_format_flow_bitmask(&b, part);
const byte *last_op = NULL; break;
const byte *op = part+1;
u64 val;
uint len;
uint first = 1;
while (1)
{
if (!first)
{
/* XXX: I don't like this so complicated if-tree */
if (!isset_and(op) && !is_bitmask(*part) &&
((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, ",");
}
else
{
buffer_puts(&b, isset_and(op) ? "&& " : "|| ");
}
}
first = 0;
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);
op += 1 + len;
len = get_value_length(op);
val = get_value(op+1, len);
buffer_print(&b, "%u", val);
}
else if (num_op(op) == FLOW_EQ)
{
buffer_print(&b, "%u", val);
}
else
{
buffer_print(&b, "%s %u", num_op_str(op), val);
}
}
if (isset_end(op))
{
buffer_puts(&b, "; ");
break;
}
else
{
buffer_puts(&b, " ");
}
last_op = op;
op += 1 + len;
}
}
} }
part = flow_next_part(part, data+dlen, ipv6); part = flow_next_part(part, data+dlen, ipv6);