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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
/*
* BIRD Internet Routing Daemon -- Attribute Operations
*
* (c) 2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_ATTRS_H_
#define _BIRD_ATTRS_H_
#include <stdint.h>
#include "lib/unaligned.h"
#include "nest/route.h"
/* a-path.c */
#define AS_PATH_SET 1 /* Types of path segments */
#define AS_PATH_SEQUENCE 2
#define AS_PATH_CONFED_SEQUENCE 3
#define AS_PATH_CONFED_SET 4
#define AS_PATH_MAXLEN 10000
#define AS_TRANS 23456
/* AS_TRANS is used when we need to store 32bit ASN larger than 0xFFFF
* to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details
*/
struct f_tree;
int as_path_valid(byte *data, uint len, int bs, int confed, char *err, uint elen);
int as_path_16to32(byte *dst, byte *src, uint len);
int as_path_32to16(byte *dst, byte *src, uint len);
int as_path_contains_as4(const struct adata *path);
int as_path_contains_confed(const struct adata *path);
struct adata *as_path_strip_confed(struct linpool *pool, const struct adata *op);
struct adata *as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as);
struct adata *as_path_to_old(struct linpool *pool, const struct adata *path);
void as_path_cut(struct adata *path, uint num);
struct adata *as_path_merge(struct linpool *pool, struct adata *p1, struct adata *p2);
void as_path_format(const struct adata *path, byte *buf, uint size);
int as_path_getlen(const struct adata *path);
int as_path_getlen_int(const struct adata *path, int bs);
int as_path_get_first(const struct adata *path, u32 *orig_as);
int as_path_get_first_regular(const struct adata *path, u32 *last_as);
int as_path_get_last(const struct adata *path, u32 *last_as);
u32 as_path_get_last_nonaggregated(const struct adata *path);
int as_path_contains(const struct adata *path, u32 as, int min);
int as_path_match_set(const struct adata *path, struct f_tree *set);
struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos);
static inline struct adata *as_path_prepend(struct linpool *pool, const struct adata *path, u32 as)
{ return as_path_prepend2(pool, path, AS_PATH_SEQUENCE, as); }
#define PM_ASN 0
#define PM_QUESTION 1
#define PM_ASTERISK 2
#define PM_ASN_EXPR 3
#define PM_ASN_RANGE 4
struct f_path_mask {
struct f_path_mask *next;
int kind;
uintptr_t val;
uintptr_t val2;
};
int as_path_match(const struct adata *path, struct f_path_mask *mask);
/* Counterparts to appropriate as_path_* functions */
static inline int
aggregator_16to32(byte *dst, byte *src)
{
put_u32(dst, get_u16(src));
memcpy(dst+4, src+2, 4);
return 8;
}
static inline int
aggregator_32to16(byte *dst, byte *src)
{
put_u16(dst, get_u32(src));
memcpy(dst+2, src+4, 4);
return 6;
}
static inline int
aggregator_contains_as4(struct adata *a)
{
return get_u32(a->data) > 0xFFFF;
}
static inline struct adata *
aggregator_to_old(struct linpool *pool, struct adata *a)
{
struct adata *d = lp_alloc_adata(pool, 8);
put_u32(d->data, 0xFFFF);
memcpy(d->data + 4, a->data + 4, 4);
return d;
}
/* a-set.c */
/* Extended Community subtypes (kinds) */
#define EC_RT 0x0002
#define EC_RO 0x0003
#define EC_GENERIC 0xFFFF
/* Transitive bit (for first u32 half of EC) */
#define EC_TBIT 0x40000000
#define ECOMM_LENGTH 8
static inline int int_set_get_size(struct adata *list)
{ return list->length / 4; }
static inline int ec_set_get_size(struct adata *list)
{ return list->length / 8; }
static inline int lc_set_get_size(struct adata *list)
{ return list->length / 12; }
static inline u32 *int_set_get_data(struct adata *list)
{ return (u32 *) list->data; }
static inline u32 ec_hi(u64 ec) { return ec >> 32; }
static inline u32 ec_lo(u64 ec) { return ec; }
static inline u64 ec_get(const u32 *l, int i)
{ return (((u64) l[i]) << 32) | l[i+1]; }
/* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
static inline u64 ec_as2(u64 kind, u64 key, u64 val)
{ return ((kind | 0x0000) << 48) | (key << 32) | val; }
/* RFC 5668 4-Octet AS Specific BGP Extended Community */
static inline u64 ec_as4(u64 kind, u64 key, u64 val)
{ return ((kind | 0x0200) << 48) | (key << 16) | val; }
/* RFC 4360 3.2. IPv4 Address Specific Extended Community */
static inline u64 ec_ip4(u64 kind, u64 key, u64 val)
{ return ((kind | 0x0100) << 48) | (key << 16) | val; }
static inline u64 ec_generic(u64 key, u64 val)
{ return (key << 32) | val; }
/* Large community value */
typedef struct lcomm {
u32 asn;
u32 ldp1;
u32 ldp2;
} lcomm;
#define LCOMM_LENGTH 12
static inline lcomm lc_get(const u32 *l, int i)
{ return (lcomm) { l[i], l[i+1], l[i+2] }; }
static inline void lc_put(u32 *l, lcomm v)
{ l[0] = v.asn; l[1] = v.ldp1; l[2] = v.ldp2; }
static inline int lc_match(const u32 *l, int i, lcomm v)
{ return (l[i] == v.asn && l[i+1] == v.ldp1 && l[i+2] == v.ldp2); }
static inline u32 *lc_copy(u32 *dst, const u32 *src)
{ memcpy(dst, src, LCOMM_LENGTH); return dst + 3; }
int int_set_format(struct adata *set, int way, int from, byte *buf, uint size);
int ec_format(byte *buf, u64 ec);
int ec_set_format(struct adata *set, int from, byte *buf, uint size);
int lc_format(byte *buf, lcomm lc);
int lc_set_format(struct adata *set, int from, byte *buf, uint size);
int int_set_contains(struct adata *list, u32 val);
int ec_set_contains(struct adata *list, u64 val);
int lc_set_contains(struct adata *list, lcomm val);
struct adata *int_set_prepend(struct linpool *pool, struct adata *list, u32 val);
struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val);
struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val);
struct adata *lc_set_add(struct linpool *pool, struct adata *list, lcomm val);
struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val);
struct adata *ec_set_del(struct linpool *pool, struct adata *list, u64 val);
struct adata *lc_set_del(struct linpool *pool, struct adata *list, lcomm val);
struct adata *int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2);
struct adata *ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2);
struct adata *lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2);
struct adata *ec_set_del_nontrans(struct linpool *pool, struct adata *set);
struct adata *int_set_sort(struct linpool *pool, struct adata *src);
struct adata *ec_set_sort(struct linpool *pool, struct adata *src);
struct adata *lc_set_sort(struct linpool *pool, struct adata *src);
void ec_set_sort_x(struct adata *set); /* Sort in place */
/* Tunnel Encapsulation TLV types */
#define TLV_WIREGUARD 0xffff
#define TLV_REMOTE_ENDPOINT 0x06
#define TLV_UDP_DEST_PORT 0x08
/* Tunnel Encapsulation TLV */
struct tlv {
union {
const char *peer;
struct {
u32 asn;
ip_addr ip;
} remote_endpoint;
u16 udp_dest_port;
u32 color;
} u;
};
#endif
|