summaryrefslogtreecommitdiff
path: root/lib/flowspec.h
blob: d486cda020ba0c91c9ceb99d647ef9674b52e67a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 *	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"


/* Flow component operators */
#define FLOW_OP_TRUE		0x00	/* 0b000 */
#define FLOW_OP_EQ		0x01	/* 0b001 */
#define FLOW_OP_GT		0x02	/* 0b010 */
#define FLOW_OP_GEQ		0x03	/* 0b011 */
#define FLOW_OP_LT		0x04	/* 0b100 */
#define FLOW_OP_LEQ		0x05	/* 0b101 */
#define FLOW_OP_NEQ		0x06	/* 0b110 */
#define FLOW_OP_FALSE		0x07	/* 0b111 */

#define FLOW_OP_OR		0x00
#define FLOW_OP_AND		0x40


/* 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_hdr_length(const byte *data)
{ return ((*data & 0xf0) == 0xf0) ? 2 : 1; }

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 accessors
 */

ip4_addr flow_read_ip4_part(const byte *part);
ip6_addr flow_read_ip6_part(const byte *part);


/*
 * 	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_INVALID_TCP_FLAGS,
  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
 */

uint flow4_net_format(char *buf, uint blen, const net_addr_flow4 *f);
uint flow6_net_format(char *buf, uint blen, const net_addr_flow6 *f);

#endif /* _BIRD_FLOWSPEC_H_ */