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