1 /*
2 * BIRD Internet Routing Daemon -- Attribute Operations
3 *
4 * (c) 2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #ifndef _BIRD_ATTRS_H_
10 #define _BIRD_ATTRS_H_
11
12 #include <stdint.h>
13 #include "lib/unaligned.h"
14 #include "nest/route.h"
15
16
17 /* a-path.c */
18
19 #define AS_PATH_SET 1 /* Types of path segments */
20 #define AS_PATH_SEQUENCE 2
21 #define AS_PATH_CONFED_SEQUENCE 3
22 #define AS_PATH_CONFED_SET 4
23
24 #define AS_PATH_MAXLEN 10000
25
26 #define AS_TRANS 23456
27 /* AS_TRANS is used when we need to store 32bit ASN larger than 0xFFFF
28 * to 16bit slot (like in 16bit AS_PATH). See RFC 4893 for details
29 */
30
31 struct f_tree;
32
33 int as_path_valid(byte *data, uint len, int bs, int sets, int confed, char *err, uint elen);
34 int as_path_16to32(byte *dst, const byte *src, uint len);
35 int as_path_32to16(byte *dst, const byte *src, uint len);
36 int as_path_contains_as4(const struct adata *path);
37 int as_path_contains_confed(const struct adata *path);
38 struct adata *as_path_strip_confed(struct linpool *pool, const struct adata *op);
39 struct adata *as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as);
40 struct adata *as_path_to_old(struct linpool *pool, const struct adata *path);
41 struct adata *as_path_cut(struct linpool *pool, const struct adata *path, uint num);
42 const struct adata *as_path_merge(struct linpool *pool, const struct adata *p1, const struct adata *p2);
43 void as_path_format(const struct adata *path, byte *buf, uint size);
44 int as_path_getlen(const struct adata *path);
45 int as_path_getlen_int(const struct adata *path, int bs);
46 int as_path_get_first(const struct adata *path, u32 *orig_as);
47 int as_path_get_first_regular(const struct adata *path, u32 *last_as);
48 int as_path_get_last(const struct adata *path, u32 *last_as);
49 u32 as_path_get_last_nonaggregated(const struct adata *path);
50 int as_path_contains(const struct adata *path, u32 as, int min);
51 int as_path_match_set(const struct adata *path, const struct f_tree *set);
52 const struct adata *as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos);
53
as_path_prepend(struct linpool * pool,const struct adata * path,u32 as)54 static inline struct adata *as_path_prepend(struct linpool *pool, const struct adata *path, u32 as)
55 { return as_path_prepend2(pool, path, AS_PATH_SEQUENCE, as); }
56
57
58 #define PM_ASN 0
59 #define PM_QUESTION 1
60 #define PM_ASTERISK 2
61 #define PM_ASN_EXPR 3
62 #define PM_ASN_RANGE 4
63 #define PM_ASN_SET 5
64 #define PM_LOOP 6
65
66 struct f_path_mask_item {
67 union {
68 u32 asn; /* PM_ASN */
69 const struct f_line *expr; /* PM_ASN_EXPR */
70 const struct f_tree *set; /* PM_ASN_SET */
71 struct { /* PM_ASN_RANGE */
72 u32 from;
73 u32 to;
74 };
75 };
76 int kind;
77 };
78
79 struct f_path_mask {
80 uint len;
81 struct f_path_mask_item item[0];
82 };
83
84 int as_path_match(const struct adata *path, const struct f_path_mask *mask);
85
86
87 /* Counterparts to appropriate as_path_* functions */
88
89 static inline int
aggregator_16to32(byte * dst,const byte * src)90 aggregator_16to32(byte *dst, const byte *src)
91 {
92 put_u32(dst, get_u16(src));
93 memcpy(dst+4, src+2, 4);
94 return 8;
95 }
96
97 static inline int
aggregator_32to16(byte * dst,const byte * src)98 aggregator_32to16(byte *dst, const byte *src)
99 {
100 put_u16(dst, get_u32(src));
101 memcpy(dst+2, src+4, 4);
102 return 6;
103 }
104
105 static inline int
aggregator_contains_as4(const struct adata * a)106 aggregator_contains_as4(const struct adata *a)
107 {
108 return get_u32(a->data) > 0xFFFF;
109 }
110
111 static inline struct adata *
aggregator_to_old(struct linpool * pool,const struct adata * a)112 aggregator_to_old(struct linpool *pool, const struct adata *a)
113 {
114 struct adata *d = lp_alloc_adata(pool, 8);
115 put_u32(d->data, AS_TRANS);
116 memcpy(d->data + 4, a->data + 4, 4);
117 return d;
118 }
119
120
121 /* a-set.c */
122
123
124 /* Extended Community subtypes (kinds) */
125 enum ec_subtype {
126 EC_RT = 0x0002,
127 EC_RO = 0x0003,
128 EC_GENERIC = 0xFFFF,
129 };
130
ec_subtype_str(const enum ec_subtype ecs)131 static inline const char *ec_subtype_str(const enum ec_subtype ecs) {
132 switch (ecs) {
133 case EC_RT: return "rt";
134 case EC_RO: return "ro";
135 default: return NULL;
136 }
137 }
138
139 /* Transitive bit (for first u32 half of EC) */
140 #define EC_TBIT 0x40000000
141
142 #define ECOMM_LENGTH 8
143
int_set_get_size(const struct adata * list)144 static inline int int_set_get_size(const struct adata *list)
145 { return list->length / 4; }
146
ec_set_get_size(const struct adata * list)147 static inline int ec_set_get_size(const struct adata *list)
148 { return list->length / 8; }
149
lc_set_get_size(const struct adata * list)150 static inline int lc_set_get_size(const struct adata *list)
151 { return list->length / 12; }
152
int_set_get_data(const struct adata * list)153 static inline u32 *int_set_get_data(const struct adata *list)
154 { return (u32 *) list->data; }
155
ec_hi(u64 ec)156 static inline u32 ec_hi(u64 ec) { return ec >> 32; }
ec_lo(u64 ec)157 static inline u32 ec_lo(u64 ec) { return ec; }
ec_get(const u32 * l,int i)158 static inline u64 ec_get(const u32 *l, int i)
159 { return (((u64) l[i]) << 32) | l[i+1]; }
160
161 /* RFC 4360 3.1. Two-Octet AS Specific Extended Community */
ec_as2(enum ec_subtype kind,u64 key,u64 val)162 static inline u64 ec_as2(enum ec_subtype kind, u64 key, u64 val)
163 { return (((u64) kind | 0x0000) << 48) | (key << 32) | val; }
164
165 /* RFC 5668 4-Octet AS Specific BGP Extended Community */
ec_as4(enum ec_subtype kind,u64 key,u64 val)166 static inline u64 ec_as4(enum ec_subtype kind, u64 key, u64 val)
167 { return (((u64) kind | 0x0200) << 48) | (key << 16) | val; }
168
169 /* RFC 4360 3.2. IPv4 Address Specific Extended Community */
ec_ip4(enum ec_subtype kind,u64 key,u64 val)170 static inline u64 ec_ip4(enum ec_subtype kind, u64 key, u64 val)
171 { return (((u64) kind | 0x0100) << 48) | (key << 16) | val; }
172
ec_generic(u64 key,u64 val)173 static inline u64 ec_generic(u64 key, u64 val)
174 { return (key << 32) | val; }
175
176 /* Large community value */
177 typedef struct lcomm {
178 u32 asn;
179 u32 ldp1;
180 u32 ldp2;
181 } lcomm;
182
183 #define LCOMM_LENGTH 12
184
lc_get(const u32 * l,int i)185 static inline lcomm lc_get(const u32 *l, int i)
186 { return (lcomm) { l[i], l[i+1], l[i+2] }; }
187
lc_put(u32 * l,lcomm v)188 static inline void lc_put(u32 *l, lcomm v)
189 { l[0] = v.asn; l[1] = v.ldp1; l[2] = v.ldp2; }
190
lc_match(const u32 * l,int i,lcomm v)191 static inline int lc_match(const u32 *l, int i, lcomm v)
192 { return (l[i] == v.asn && l[i+1] == v.ldp1 && l[i+2] == v.ldp2); }
193
lc_copy(u32 * dst,const u32 * src)194 static inline u32 *lc_copy(u32 *dst, const u32 *src)
195 { memcpy(dst, src, LCOMM_LENGTH); return dst + 3; }
196
197
198 int int_set_format(const struct adata *set, int way, int from, byte *buf, uint size);
199 int ec_format(byte *buf, u64 ec);
200 int ec_set_format(const struct adata *set, int from, byte *buf, uint size);
201 int lc_format(byte *buf, lcomm lc);
202 int lc_set_format(const struct adata *set, int from, byte *buf, uint size);
203 int int_set_contains(const struct adata *list, u32 val);
204 int ec_set_contains(const struct adata *list, u64 val);
205 int lc_set_contains(const struct adata *list, lcomm val);
206 const struct adata *int_set_prepend(struct linpool *pool, const struct adata *list, u32 val);
207 const struct adata *int_set_add(struct linpool *pool, const struct adata *list, u32 val);
208 const struct adata *ec_set_add(struct linpool *pool, const struct adata *list, u64 val);
209 const struct adata *lc_set_add(struct linpool *pool, const struct adata *list, lcomm val);
210 const struct adata *int_set_del(struct linpool *pool, const struct adata *list, u32 val);
211 const struct adata *ec_set_del(struct linpool *pool, const struct adata *list, u64 val);
212 const struct adata *lc_set_del(struct linpool *pool, const struct adata *list, lcomm val);
213 const struct adata *int_set_union(struct linpool *pool, const struct adata *l1, const struct adata *l2);
214 const struct adata *ec_set_union(struct linpool *pool, const struct adata *l1, const struct adata *l2);
215 const struct adata *lc_set_union(struct linpool *pool, const struct adata *l1, const struct adata *l2);
216
217 struct adata *ec_set_del_nontrans(struct linpool *pool, const struct adata *set);
218 struct adata *int_set_sort(struct linpool *pool, const struct adata *src);
219 struct adata *ec_set_sort(struct linpool *pool, const struct adata *src);
220 struct adata *lc_set_sort(struct linpool *pool, const struct adata *src);
221
222 void ec_set_sort_x(struct adata *set); /* Sort in place */
223
224 #endif
225