Commit 77234bbb authored by Ondřej Zajíček's avatar Ondřej Zajíček

Basic flow specification support (RFC 5575)

Add flow4/flow6 network and rt-table type and operations, config grammar
and static protocol support.

Squashed flowspec branch from Pavel Tvrdik.
parent b94e5e58
......@@ -10,7 +10,7 @@ BISON_DEBUG=-t
#FLEX_DEBUG=-d
endif
$(conf-y-targets): $(s)confbase.Y
$(conf-y-targets): $(s)confbase.Y $(s)flowspec.Y
$(M4) -P $| $^ >$@
$(o)cf-parse.y: | $(s)gen_parser.m4
......
......@@ -138,8 +138,6 @@ expr_us:
| expr US { $$ = (u32) $1 * 1; }
;
/* expr_u16: expr { check_u16($1); $$ = $1; }; */
/* Switches */
bool:
......@@ -220,6 +218,7 @@ net_roa_: net_roa4_ | net_roa6_ ;
net_:
net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
| net_roa_
| net_flow_
;
......
/*
* BIRD -- Flow specification (RFC 5575) grammar
*
* (c) 2016 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
CF_HDR
#define PARSER 1
#include "nest/bird.h"
#include "conf/conf.h"
#include "lib/resource.h"
#include "lib/socket.h"
#include "sysdep/unix/timer.h"
#include "lib/string.h"
#include "nest/protocol.h"
#include "nest/iface.h"
#include "nest/route.h"
#include "nest/cli.h"
#include "filter/filter.h"
#include "lib/flowspec.h"
CF_DEFINES
struct flow_builder *this_flow;
CF_DECLS
%type <i32> flow_num_op flow_srcdst flow_logic_op flow_num_type_ flow_frag_val flow_neg
%type <net_ptr> net_flow4_ net_flow6_ net_flow_
CF_KEYWORDS(FLOW4, FLOW6, DST, SRC, PROTO, NEXT, HEADER, DPORT, SPORT, ICMP,
TYPE, CODE, TCP, FLAGS, LENGTH, DSCP, DONT_FRAGMENT, IS_FRAGMENT,
FIRST_FRAGMENT, LAST_FRAGMENT, FRAGMENT, LABEL, OFFSET)
CF_GRAMMAR
/* Network Flow Specification */
flow_num_op:
TRUE { $$ = 0b000; }
| '=' { $$ = 0b001; }
| NEQ { $$ = 0b110; }
| '<' { $$ = 0b100; }
| LEQ { $$ = 0b101; }
| '>' { $$ = 0b010; }
| GEQ { $$ = 0b011; }
| FALSE { $$ = 0b111; }
;
flow_logic_op:
OR { $$ = 0x00; }
| AND { $$ = 0x40; }
;
flow_num_type_:
PROTO { $$ = FLOW_TYPE_IP_PROTOCOL; }
| NEXT HEADER { $$ = FLOW_TYPE_NEXT_HEADER; }
| PORT { $$ = FLOW_TYPE_PORT; }
| DPORT { $$ = FLOW_TYPE_DST_PORT; }
| SPORT { $$ = FLOW_TYPE_SRC_PORT; }
| ICMP TYPE { $$ = FLOW_TYPE_ICMP_TYPE; }
| ICMP CODE { $$ = FLOW_TYPE_ICMP_CODE; }
| LENGTH { $$ = FLOW_TYPE_PACKET_LENGTH; }
| DSCP { $$ = FLOW_TYPE_DSCP; }
;
flow_num_type: flow_num_type_{ flow_builder_set_type(this_flow, $1); };
flow_flag_type: TCP FLAGS { flow_builder_set_type(this_flow, FLOW_TYPE_TCP_FLAGS); };
flow_frag_type: FRAGMENT { flow_builder_set_type(this_flow, FLOW_TYPE_FRAGMENT); };
flow_label_type: LABEL { flow_builder_set_type(this_flow, FLOW_TYPE_LABEL); };
flow_srcdst:
DST { $$ = FLOW_TYPE_DST_PREFIX; }
| SRC { $$ = FLOW_TYPE_SRC_PREFIX; }
;
flow_num_opts:
flow_num_op expr {
flow_check_cf_value_length(this_flow, $2);
flow_builder_add_op_val(this_flow, $1, $2);
}
| flow_num_opts flow_logic_op flow_num_op expr {
flow_check_cf_value_length(this_flow, $4);
flow_builder_add_op_val(this_flow, $2 | $3, $4);
}
| flow_num_opt_ext
| flow_num_opts OR flow_num_opt_ext
;
flow_num_opt_ext_expr:
expr {
flow_check_cf_value_length(this_flow, $1);
flow_builder_add_op_val(this_flow, 0b001, $1);
}
| expr DDOT expr {
flow_check_cf_value_length(this_flow, $1);
flow_check_cf_value_length(this_flow, $3);
flow_builder_add_op_val(this_flow, 0b011, $1); /* >= */
flow_builder_add_op_val(this_flow, 0x40 | 0b101, $3); /* AND <= */
}
;
flow_num_opt_ext:
flow_num_opt_ext_expr
| flow_num_opt_ext ',' flow_num_opt_ext_expr
;
flow_bmk_opts:
flow_neg expr '/' expr {
flow_check_cf_bmk_values(this_flow, $1, $2, $4);
flow_builder_add_val_mask(this_flow, $1, $2, $4);
}
| flow_bmk_opts flow_logic_op flow_neg expr '/' expr {
flow_check_cf_bmk_values(this_flow, $3, $4, $6);
flow_builder_add_val_mask(this_flow, $2 | $3, $4, $6);
}
| flow_bmk_opts ',' flow_neg expr '/' expr {
flow_check_cf_bmk_values(this_flow, $3, $4, $6);
flow_builder_add_val_mask(this_flow, 0x40 | $3, $4, $6); /* AND */
}
;
flow_neg:
/* empty */ { $$ = 0x00; }
| '!' { $$ = 0x02; }
;
flow_frag_val:
DONT_FRAGMENT { $$ = 1; }
| IS_FRAGMENT { $$ = 2; }
| FIRST_FRAGMENT { $$ = 4; }
| LAST_FRAGMENT { $$ = 8; }
;
flow_frag_opts:
flow_neg flow_frag_val {
flow_builder_add_val_mask(this_flow, 0, ($1 ? 0 : $2), $2);
}
| flow_frag_opts flow_logic_op flow_neg flow_frag_val {
flow_builder_add_val_mask(this_flow, $2, ($3 ? 0 : $4), $4);
}
| flow_frag_opts ',' flow_neg flow_frag_val {
flow_builder_add_val_mask(this_flow, 0x40, ($3 ? 0 : $4), $4); /* AND */
}
;
flow4_item:
flow_srcdst net_ip {
flow_builder_set_type(this_flow, $1);
flow_builder4_add_pfx(this_flow, (net_addr_ip4 *) &($2));
}
| flow_num_type flow_num_opts
| flow_flag_type flow_bmk_opts
| flow_frag_type flow_frag_opts
;
flow6_item:
flow_srcdst net_ip6 {
flow_builder_set_type(this_flow, $1);
flow_builder6_add_pfx(this_flow, (net_addr_ip6 *) &($2), 0);
}
| flow_srcdst net_ip6 OFFSET NUM {
if ($4 > $2.pxlen)
cf_error("Prefix offset is higher than prefix length");
flow_builder_set_type(this_flow, $1);
flow_builder6_add_pfx(this_flow, (net_addr_ip6 *) &($2), $4);
}
| flow_num_type flow_num_opts
| flow_flag_type flow_bmk_opts
| flow_frag_type flow_frag_opts
| flow_label_type flow_bmk_opts
;
flow4_opts:
/* empty */
| flow4_opts flow4_item ';'
;
flow6_opts:
/* empty */
| flow6_opts flow6_item ';'
;
flow_builder_init:
{
if (this_flow == NULL)
this_flow = flow_builder_init(&root_pool);
else
flow_builder_clear(this_flow);
};
flow_builder_set_ipv4: { this_flow->ipv6 = 0; };
flow_builder_set_ipv6: { this_flow->ipv6 = 1; };
net_flow4_: FLOW4 '{' flow_builder_init flow_builder_set_ipv4 flow4_opts '}'
{
$$ = (net_addr *) flow_builder4_finalize(this_flow, cfg_mem);
flow4_validate_cf((net_addr_flow4 *) $$);
};
net_flow6_: FLOW6 '{' flow_builder_init flow_builder_set_ipv6 flow6_opts '}'
{
$$ = (net_addr *) flow_builder6_finalize(this_flow, cfg_mem);
flow6_validate_cf((net_addr_flow6 *) $$);
};
net_flow_: net_flow4_ | net_flow6_ ;
CF_CODE
CF_END
......@@ -715,6 +715,137 @@ agreement").
</descrip>
<sect>Flowspec network type
<label id="flowspec-network-type">
<p>The flow specification are rules for routers and firewalls for filtering
purpose. It is described by <rfc id="5575">. There are 3 types of arguments:
<m/inet4/ or <m/inet6/ prefixes, bitmasks matching expressions and numbers
matching expressions.
Bitmasks matching is written using <m/value/<cf>/</cf><m/mask/ or
<cf/!/<m/value/<cf>/</cf><m/mask/ pairs. It means that <cf/(/<m/data/ <cf/&/
<m/mask/<cf/)/ is or is not equal to <m/value/.
Numbers matching is a matching sequence of numbers and ranges separeted by a
commas (<cf/,/) (e.g. <cf/10,20,30/). Ranges can be written using double dots
<cf/../ notation (e.g. <cf/80..90,120..124/). An alternative notation are
sequence of one or more pairs of relational operators and values separated by
logical operators <cf/&&/ or <cf/||/. Allowed relational operators are <cf/=/,
<cf/!=/, <cf/</, <cf/<=/, <cf/>/, <cf/>=/, <cf/true/ and <cf/false/.
<sect1>IPv4 Flowspec
<p><descrip>
<tag><label id="flow-dst">dst <m/inet4/</tag>
Set a matching destination prefix (e.g. <cf>dst 192.168.0.0/16</cf>).
Only this option is mandatory in IPv4 Flowspec.
<tag><label id="flow-src">src <m/inet4/</tag>
Set a matching source prefix (e.g. <cf>src 10.0.0.0/8</cf>).
<tag><label id="flow-proto">proto <m/numbers-match/</tag>
Set a matching IP protocol numbers (e.g. <cf/proto 6/).
<tag><label id="flow-port">port <m/numbers-match/</tag>
Set a matching source or destination TCP/UDP port numbers (e.g.
<cf>port 1..1023,1194,3306</cf>).
<tag><label id="flow-dport">dport <m/numbers-match/</tag>
Set a mating destination port numbers (e.g. <cf>dport 49151</cf>).
<tag><label id="flow-sport">sport <m/numbers-match/</tag>
Set a matching source port numbers (e.g. <cf>sport = 0</cf>).
<tag><label id="flow-icmp-type">icmp type <m/numbers-match/</tag>
Set a matching type field number of an ICMP packet (e.g. <cf>icmp type
3</cf>)
<tag><label id="flow-icmp-code">icmp code <m/numbers-match/</tag>
Set a matching code field number of an ICMP packet (e.g. <cf>icmp code
1</cf>)
<tag><label id="flow-tcp-flags">tcp flags <m/bitmask-match/</tag>
Set a matching bitmask for TCP header flags (aka control bits) (e.g.
<cf>tcp flags 0x03/0x0f;</cf>).
<tag><label id="flow-length">length <m/numbers-match/</tag>
Set a matching packet length (e.g. <cf>length > 1500;</cf>)
<tag><label id="flow-dscp">dscp <m/numbers-match/</tag>
Set a matching DiffServ Code Point number (e.g. <cf>length > 1500;</cf>).
<tag><label id="flow-fragment">fragment <m/fragmentation-type/</tag>
Set a matching type of packet fragmentation. Allowed fragmentation
types are <cf/dont_fragment/, <cf/is_fragment/, <cf/first_fragment/,
<cf/last_fragment/ (e.g. <cf>fragment is_fragment &&
!dont_fragment</cf>).
</descrip>
<p><code>
protocol static {
flow4;
route flow4 {
dst 10.0.0.0/8;
port > 24 && < 30 || 40..50,60..70,80 && >= 90;
tcp flags 0x03/0x0f;
length > 1024;
dscp = 63;
fragment dont_fragment, is_fragment || !first_fragment;
} drop;
}
</code>
<sect1>Differences for IPv6 Flowspec
<p>Flowspec IPv6 are same as Flowspec IPv4 with a few exceptions.
<itemize>
<item>Prefixes <m/inet6/ can be specified not only with prefix length,
but with prefix <cf/offset/ <m/num/ too (e.g.
<cf>::1234:5678:9800:0000/101 offset 64</cf>). Offset means to don't
care of <m/num/ first bits.
<item>IPv6 Flowspec hasn't mandatory any flowspec component.
<item>In IPv6 packets, there is a matching the last next header value
for a matching IP protocol number (e.g. <cf>next header 6</cf>).
<item>It is not possible to set <cf>dont_fragment</cf> as a type of
packet fragmentation.
</itemize>
<p><descrip>
<tag><label id="flow6-dst">dst <m/inet6/ [offset <m/num/]</tag>
Set a matching destination IPv6 prefix (e.g. <cf>dst
::1c77:3769:27ad:a11a/128 offset 64</cf>).
<tag><label id="flow6-src">src <m/inet6/ [offset <m/num/]</tag>
Set a matching source IPv6 prefix (e.g. <cf>src fe80::/64</cf>).
<tag><label id="flow6-next-header">next header <m/numbers-match/</tag>
Set a matching IP protocol numbers (e.g. <cf>next header != 6</cf>).
<tag><label id="flow6-label">label <m/bitmask-match/</tag>
Set a 20-bit bitmask for matching Flow Label field in IPv6 packets
(e.g. <cf>label 0x8e5/0x8e5</cf>).
</descrip>
<p><code>
protocol static {
flow6;
route flow6 {
dst fec0:1122:3344:5566:7788:99aa:bbcc:ddee/128;
src 0000:0000:0000:0001:1234:5678:9800:0000/101 offset 63;
next header = 23;
sport > 24 && < 30 || = 40 || 50,60,70..80;
dport = 50;
tcp flags 0x03/0x0f, !0/0xff || 0x33/0x33;
fragment !is_fragment || !first_fragment;
label 0xaaaa/0xaaaa && 0x33/0x33;
} drop;
}
</code>
<chapt>Remote control
<label id="remote-control">
......
......@@ -548,6 +548,32 @@ bt_test_suite(t_prefix6_set, "Testing prefix IPv6 sets");
function t_flowspec()
prefix p;
{
p = flow4 { dst 10.0.0.0/8; };
bt_assert(p !~ [ 10.0.0.0/8 ] );
bt_assert(format(flow4 { dst 10.0.0.0/8; proto = 23; }) = "flow4 { dst 10.0.0.0/8; proto 23; }");
bt_assert(format(flow6 { dst ::1/128; src ::2/127; }) = "flow6 { dst ::1/128; src ::2/127; }");
bt_assert(format(flow6 { next header false 42; }) = "flow6 { next header false 42; }");
bt_assert(format(flow6 { port 80; }) = "flow6 { port 80; }");
bt_assert(format(flow6 { dport > 24 && < 30 || 40..50,60..70,80 && >= 90; }) = "flow6 { dport > 24 && < 30 || 40..50,60..70,80 && >= 90; }");
bt_assert(format(flow6 { sport 0..0x400; }) = "flow6 { sport 0..1024; }");
bt_assert(format(flow6 { icmp type 80; }) = "flow6 { icmp type 80; }");
bt_assert(format(flow6 { icmp code 90; }) = "flow6 { icmp code 90; }");
bt_assert(format(flow6 { tcp flags 0x03/0x0f; }) = "flow6 { tcp flags 0x3/0x3,0x0/0xc; }");
bt_assert(format(flow6 { length 0..65535; }) = "flow6 { length 0..65535; }");
bt_assert(format(flow6 { dscp = 63; }) = "flow6 { dscp 63; }");
bt_assert(format(flow6 { fragment is_fragment || !first_fragment; }) = "flow6 { fragment is_fragment || !first_fragment; }");
bt_assert(format(flow6 { }) = "flow6 { }");
}
bt_test_suite(t_flowspec, "Testing flowspec routes");
/*
* Testing Paths
* -------------
......
......@@ -3,6 +3,7 @@ S ip.c
S lists.c
S checksum.c bitops.c patmatch.c printf.c xmalloc.c tbf.c
S mac.c
S flowspec.c
D resource.sgml
S resource.c
S mempool.c
......
......@@ -2,10 +2,10 @@ src := bitops.c checksum.c ip.c lists.c md5.c net.c patmatch.c printf.c sha1.c s
obj := $(src-o-files)
$(all-client)
src := bitops.c checksum.c event.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c
src := bitops.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c
obj := $(src-o-files)
$(all-daemon)
tests_src := heap_test.c buffer_test.c event_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c checksum_test.c lists_test.c mac_test.c ip_test.c hash_test.c printf_test.c
tests_src := heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c checksum_test.c lists_test.c mac_test.c ip_test.c hash_test.c printf_test.c
tests_targets := $(tests_targets) $(tests-target-files)
tests_objs := $(tests_objs) $(src-o-files)
......@@ -34,6 +34,7 @@
#define ABS(a) ((a)>=0 ? (a) : -(a))
#define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
#define BYTES(n) ((((uint) (n)) + 7) / 8)
#define CALL(fn, args...) ({ if (fn) fn(args); })
#define ADVANCE(w, r, l) ({ r -= l; w += l; })
......
......@@ -46,4 +46,11 @@
#define BUFFER_FLUSH(v) ({ (v).used = 0; })
#define BUFFER_SHALLOW_COPY(dst, src) \
({ \
(dst).used = (src).used; \
(dst).size = (src).size; \
(dst).data = (src).data; \
})
#endif /* _BIRD_BUFFER_H_ */
This diff is collapsed.
/*
* BIRD Library -- Flow specification (RFC 5575)
*
* (c) 2016 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_FLOWSPEC_H_
#define _BIRD_FLOWSPEC_H_
#include "nest/bird.h"
#include "lib/buffer.h"
#include "lib/net.h"
/* Types of components in flowspec */
enum flow_type {
FLOW_TYPE_DST_PREFIX = 1,
FLOW_TYPE_SRC_PREFIX = 2,
FLOW_TYPE_IP_PROTOCOL = 3,
FLOW_TYPE_NEXT_HEADER = 3, /* IPv6 */
FLOW_TYPE_PORT = 4,
FLOW_TYPE_DST_PORT = 5,
FLOW_TYPE_SRC_PORT = 6,
FLOW_TYPE_ICMP_TYPE = 7,
FLOW_TYPE_ICMP_CODE = 8,
FLOW_TYPE_TCP_FLAGS = 9,
FLOW_TYPE_PACKET_LENGTH = 10,
FLOW_TYPE_DSCP = 11, /* DiffServ Code Point */
FLOW_TYPE_FRAGMENT = 12,
FLOW_TYPE_LABEL = 13, /* IPv6 */
FLOW_TYPE_MAX
};
const char *flow_type_str(enum flow_type type, int ipv6);
/*
* Length
*/
uint flow_write_length(byte *data, u16 len);
static inline u16 flow_read_length(const byte *data)
{ return ((*data & 0xf0) == 0xf0) ? get_u16(data) & 0x0fff : *data; }
static inline u16 flow4_get_length(const net_addr_flow4 *f)
{ return f->length - sizeof(net_addr_flow4); }
static inline u16 flow6_get_length(const net_addr_flow6 *f)
{ return f->length - sizeof(net_addr_flow6); }
static inline void flow4_set_length(net_addr_flow4 *f, u16 len)
{ f->length = sizeof(net_addr_flow4) + flow_write_length(f->data, len) + len; }
static inline void flow6_set_length(net_addr_flow6 *f, u16 len)
{ f->length = sizeof(net_addr_flow6) + flow_write_length(f->data, len) + len; }
/*
* Iterators
*/
const byte *flow4_first_part(const net_addr_flow4 *f);
const byte *flow6_first_part(const net_addr_flow6 *f);
const byte *flow4_next_part(const byte *pos, const byte *end);
const byte *flow6_next_part(const byte *pos, const byte *end);
/*
* Flowspec Builder
*/
/* A data structure for keep a state of flow builder */
struct flow_builder {
BUFFER(byte) data;
enum flow_type this_type;
enum flow_type last_type;
u16 last_op_offset; /* Position of last operator in data.data */
int ipv6;
struct {
u16 offset; /* Beginning of a component */
u16 length; /* Length of a component */
} parts[FLOW_TYPE_MAX]; /* Indexing all components */
};
struct flow_builder *flow_builder_init(pool *pool);
void flow_builder_clear(struct flow_builder *fb);
void flow_builder_set_type(struct flow_builder *fb, enum flow_type p);
int flow_builder4_add_pfx(struct flow_builder *fb, const net_addr_ip4 *n4);
int flow_builder6_add_pfx(struct flow_builder *fb, const net_addr_ip6 *n6, u32 offset);
int flow_builder_add_op_val(struct flow_builder *fb, byte op, u32 value);
int flow_builder_add_val_mask(struct flow_builder *fb, byte op, u32 value, u32 mask);
net_addr_flow4 *flow_builder4_finalize(struct flow_builder *fb, linpool *lpool);
net_addr_flow6 *flow_builder6_finalize(struct flow_builder *fb, linpool *lpool);
/*
* Validation
*/
/* Results of validation Flow specification */
enum flow_validated_state {
FLOW_ST_UNKNOWN_COMPONENT,
FLOW_ST_VALID,
FLOW_ST_NOT_COMPLETE,
FLOW_ST_EXCEED_MAX_PREFIX_LENGTH,
FLOW_ST_EXCEED_MAX_PREFIX_OFFSET,
FLOW_ST_EXCEED_MAX_VALUE_LENGTH,
FLOW_ST_BAD_TYPE_ORDER,
FLOW_ST_AND_BIT_SHOULD_BE_UNSET,
FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED,
FLOW_ST_DEST_PREFIX_REQUIRED,
FLOW_ST_CANNOT_USE_DONT_FRAGMENT
};
const char *flow_validated_state_str(enum flow_validated_state code);
enum flow_validated_state flow4_validate(const byte *nlri, uint len);
enum flow_validated_state flow6_validate(const byte *nlri, uint len);
void flow_check_cf_value_length(struct flow_builder *fb, u32 expr);
void flow_check_cf_bmk_values(struct flow_builder *fb, u8 neg, u32 val, u32 mask);
void flow4_validate_cf(net_addr_flow4 *f);
void flow6_validate_cf(net_addr_flow6 *f);
/*
* Net Formatting
*/
int flow4_net_format(char *buf, uint blen, const net_addr_flow4 *f);
int flow6_net_format(char *buf, uint blen, const net_addr_flow6 *f);
#endif /* _BIRD_FLOWSPEC_H_ */
This diff is collapsed.
......@@ -2,42 +2,51 @@
#include "nest/bird.h"
#include "lib/ip.h"
#include "lib/net.h"
#include "lib/flowspec.h"
const char * const net_label[] = {
[NET_IP4] = "ipv4",
[NET_IP6] = "ipv6",
[NET_VPN4] = "vpn4",
[NET_VPN6] = "vpn6",
[NET_ROA4] = "roa4",
[NET_ROA6] = "roa6",
[NET_IP4] = "ipv4",
[NET_IP6] = "ipv6",
[NET_VPN4] = "vpn4",
[NET_VPN6] = "vpn6",
[NET_ROA4] = "roa4",
[NET_ROA6] = "roa6",
[NET_FLOW4] = "flow4",
[NET_FLOW6] = "flow6"
};
const u16 net_addr_length[] = {
[NET_IP4] = sizeof(net_addr_ip4),
[NET_IP6] = sizeof(net_addr_ip6),
[NET_VPN4] = sizeof(net_addr_vpn4),
[NET_VPN6] = sizeof(net_addr_vpn6),
[NET_ROA4] = sizeof(net_addr_roa4),
[NET_ROA6] = sizeof(net_addr_roa6)
[NET_IP4] = sizeof(net_addr_ip4),
[NET_IP6] = sizeof(net_addr_ip6),
[NET_VPN4] = sizeof(net_addr_vpn4),
[NET_VPN6] = sizeof(net_addr_vpn6),
[NET_ROA4] = sizeof(net_addr_roa4),
[NET_ROA6] = sizeof(net_addr_roa6),
[NET_FLOW4] = 0,
[NET_FLOW6] = 0
};
const u8 net_max_prefix_length[] = {
[NET_IP4] = IP4_MAX_PREFIX_LENGTH,
[NET_IP6] = IP6_MAX_PREFIX_LENGTH,
[NET_VPN4] = IP4_MAX_PREFIX_LENGTH,
[NET_VPN6] = IP6_MAX_PREFIX_LENGTH,
[NET_ROA4] = IP4_MAX_PREFIX_LENGTH,
[NET_ROA6] = IP6_MAX_PREFIX_LENGTH
[NET_IP4] = IP4_MAX_PREFIX_LENGTH,
[NET_IP6] = IP6_MAX_PREFIX_LENGTH,
[NET_VPN4] = IP4_MAX_PREFIX_LENGTH,
[NET_VPN6] = IP6_MAX_PREFIX_LENGTH,
[NET_ROA4] = IP4_MAX_PREFIX_LENGTH,
[NET_ROA6] = IP6_MAX_PREFIX_LENGTH,
[NET_FLOW4] = IP4_MAX_PREFIX_LENGTH,
[NET_FLOW6] = IP6_MAX_PREFIX_LENGTH
};
const u16 net_max_text_length[] = {
[NET_IP4] = 18, /* "255.255.255.255/32" */
[NET_IP6] = 43, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
[NET_VPN4] = 40, /* "4294967296:4294967296 255.255.255.255/32" */
[NET_VPN6] = 65, /* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
[NET_ROA4] = 34, /* "255.255.255.255/32-32 AS4294967295" */
[NET_ROA6] = 60, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
[NET_IP4] = 18, /* "255.255.255.255/32" */
[NET_IP6] = 43, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
[NET_VPN4] = 40, /* "4294967296:4294967296 255.255.255.255/32" */
[NET_VPN6] = 65, /* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
[NET_ROA4] = 34, /* "255.255.255.255/32-32 AS4294967295" */
[NET_ROA6] = 60, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
[NET_FLOW4] = 0, /* "flow4 { ... }" */
[NET_FLOW6] = 0 /* "flow6 { ... }" */
};
......@@ -60,6 +69,10 @@ net_format(const net_addr *N, char *buf, int buflen)
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
case NET_ROA6:
return bsnprintf(buf, buflen, "%I6/%u-%u AS%u", n->roa6.prefix, n->roa6.pxlen, n->roa6.max_pxlen, n->roa6.asn);
case NET_FLOW4:
return flow4_net_format(buf, buflen, &n->flow4);
case NET_FLOW6:
return flow6_net_format(buf, buflen, &n->flow6);
}
return 0;
......@@ -73,11 +86,13 @@ net_pxmask(const net_addr *a)
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
case NET_FLOW4:
return ipa_from_ip4(ip4_mkmask(net4_pxlen(a)));
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
case NET_FLOW6:
return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
default:
......@@ -105,6 +120,10 @@ net_compare(const net_addr *a, const net_addr *b)
return net_compare_roa4((const net_addr_roa4 *) a, (const net_addr_roa4 *) b);
case NET_ROA6:
return net_compare_roa6((const net_addr_roa6 *) a, (const net_addr_roa6 *) b);
case NET_FLOW4:
return net_compare_flow4((const net_addr_flow4 *) a, (const net_addr_flow4 *) b);
case NET_FLOW6:
return net_compare_flow6((const net_addr_flow6 *) a, (const net_addr_flow6 *) b);
}
return 0;
}
......@@ -122,6 +141,8 @@ net_hash(const net_addr *n)
case NET_VPN6: return NET_HASH(n, vpn6);
case NET_ROA4: return NET_HASH(n, roa4);
case NET_ROA6: return NET_HASH(n, roa6);
case NET_FLOW4: return NET_HASH(n, flow4);
case NET_FLOW6: return NET_HASH(n, flow6);
default: bug("invalid type");
}
}
......@@ -135,11 +156,13 @@ net_validate(const net_addr *N)
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
case NET_FLOW4:
return net_validate_ip4((net_addr_ip4 *) N);
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
case NET_FLOW6:
return net_validate_ip6((net_addr_ip6 *) N);
default:
......@@ -157,11 +180,13 @@ net_normalize(net_addr *N)
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
case NET_FLOW4:
return net_normalize_ip4(&n->ip4);
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
case NET_FLOW6:
return net_normalize_ip6(&n->ip6);
}
}
......@@ -176,11 +201,13 @@ net_classify(const net_addr *N)
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
case NET_FLOW4:
return ip4_zero(n->ip4.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip4_classify(n->ip4.prefix);
case NET_IP6:
case NET_VPN6:
case NET_ROA6:
case NET_FLOW6:
return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
}
......@@ -195,6 +222,7 @@ ipa_in_netX(const ip_addr a, const net_addr *n)
case NET_IP4:
case NET_VPN4:
case NET_ROA4:
case NET_FLOW4: