flowspec.h 4.43 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *	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"


17 18 19 20 21 22 23 24 25 26 27 28 29 30
/* 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


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
/* 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);

59 60 61
static inline u16 flow_hdr_length(const byte *data)
{ return ((*data & 0xf0) == 0xf0) ? 2 : 1; }

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
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 {
94
  BUFFER_(byte) data;
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
  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,
132
  FLOW_ST_INVALID_TCP_FLAGS,
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
  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
 */

Ondřej Zajíček's avatar
Ondřej Zajíček committed
149 150
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);
151 152

#endif /* _BIRD_FLOWSPEC_H_ */