11 |
11 |
#undef LOCAL_DEBUG
|
12 |
12 |
|
13 |
13 |
#include <stdlib.h>
|
|
14 |
#include <string.h>
|
|
15 |
#include <stdio.h>
|
14 |
16 |
|
15 |
17 |
#include "nest/bird.h"
|
16 |
18 |
#include "nest/iface.h"
|
... | ... | |
64 |
66 |
* format - Optional hook that converts eattr to textual representation.
|
65 |
67 |
*/
|
66 |
68 |
|
67 |
|
|
68 |
69 |
struct bgp_attr_desc {
|
69 |
|
const char *name;
|
70 |
|
uint type;
|
71 |
|
uint flags;
|
72 |
|
void (*export)(struct bgp_export_state *s, eattr *a);
|
73 |
|
int (*encode)(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
74 |
|
void (*decode)(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to);
|
75 |
|
void (*format)(eattr *ea, byte *buf, uint size);
|
|
70 |
const char *name;
|
|
71 |
uint type;
|
|
72 |
uint flags;
|
|
73 |
void (*export)(struct bgp_export_state *s, eattr *a);
|
|
74 |
int (*encode)(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
|
75 |
void (*decode)(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to);
|
|
76 |
void (*format)(eattr *ea, byte *buf, uint size);
|
76 |
77 |
};
|
77 |
78 |
|
78 |
79 |
static const struct bgp_attr_desc bgp_attr_table[];
|
79 |
80 |
|
80 |
81 |
static inline int bgp_attr_known(uint code);
|
81 |
82 |
|
|
83 |
|
|
84 |
/**
|
|
85 |
* This function initialize the map used for the RT and the ASLoad map
|
|
86 |
*
|
|
87 |
* @author Mattia Milani
|
|
88 |
*/
|
|
89 |
void initRTmap(){
|
|
90 |
//Map init
|
|
91 |
map_init(&RTmap);
|
|
92 |
map_init(&ExternalDestinationMap);
|
|
93 |
map_init(&ASLoad_map);
|
|
94 |
//Variable setting
|
|
95 |
esportoDestinazioni = 0;
|
|
96 |
total_number_of_update_sent = 0;
|
|
97 |
}
|
|
98 |
|
|
99 |
/**
|
|
100 |
* Init function for the init of a RT element to be loaded in the data structure
|
|
101 |
* @param dest Destination addr
|
|
102 |
* @param l Load
|
|
103 |
* @param inter Define if an addr is intern or extern
|
|
104 |
* @return Return the RTable element
|
|
105 |
*/
|
|
106 |
RTable
|
|
107 |
initRTableElement(net_addr *dest, int l, int inter){
|
|
108 |
RTable element;
|
|
109 |
element.interno = inter;
|
|
110 |
element.d = dest;
|
|
111 |
map_init(&element.NH);
|
|
112 |
map_init(&element.loadin);
|
|
113 |
element.load = l;
|
|
114 |
return element;
|
|
115 |
}
|
|
116 |
|
82 |
117 |
eattr *
|
83 |
|
bgp_set_attr(ea_list **attrs, struct linpool *pool, uint code, uint flags, uintptr_t val)
|
|
118 |
bgp_set_attr(ea_list **attrs, struct linpool *pool, uint code, uint flags, uintptr_t val)
|
84 |
119 |
{
|
85 |
|
ASSERT(bgp_attr_known(code));
|
|
120 |
ASSERT(bgp_attr_known(code));
|
86 |
121 |
|
87 |
|
ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
|
88 |
|
eattr *e = &a->attrs[0];
|
|
122 |
ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
|
|
123 |
eattr *e = &a->attrs[0];
|
89 |
124 |
|
90 |
|
a->flags = EALF_SORTED;
|
91 |
|
a->count = 1;
|
92 |
|
a->next = *attrs;
|
93 |
|
*attrs = a;
|
|
125 |
a->flags = EALF_SORTED;
|
|
126 |
a->count = 1;
|
|
127 |
a->next = *attrs;
|
|
128 |
*attrs = a;
|
94 |
129 |
|
95 |
|
e->id = EA_CODE(EAP_BGP, code);
|
96 |
|
e->type = bgp_attr_table[code].type;
|
97 |
|
e->flags = flags;
|
|
130 |
e->id = EA_CODE(EAP_BGP, code);
|
|
131 |
e->type = bgp_attr_table[code].type;
|
|
132 |
e->flags = flags;
|
98 |
133 |
|
99 |
|
if (e->type & EAF_EMBEDDED)
|
100 |
|
e->u.data = (u32) val;
|
101 |
|
else
|
102 |
|
e->u.ptr = (struct adata *) val;
|
|
134 |
if (e->type & EAF_EMBEDDED)
|
|
135 |
e->u.data = (u32) val;
|
|
136 |
else
|
|
137 |
e->u.ptr = (struct adata *) val;
|
103 |
138 |
|
104 |
|
return e;
|
|
139 |
return e;
|
105 |
140 |
}
|
106 |
141 |
|
107 |
|
|
108 |
|
|
109 |
142 |
#define REPORT(msg, args...) \
|
110 |
143 |
({ log(L_REMOTE "%s: " msg, s->proto->p.name, ## args); })
|
111 |
144 |
|
... | ... | |
128 |
161 |
static inline int
|
129 |
162 |
bgp_put_attr_hdr3(byte *buf, uint code, uint flags, uint len)
|
130 |
163 |
{
|
131 |
|
*buf++ = flags;
|
132 |
|
*buf++ = code;
|
133 |
|
*buf++ = len;
|
134 |
|
return 3;
|
|
164 |
*buf++ = flags;
|
|
165 |
*buf++ = code;
|
|
166 |
*buf++ = len;
|
|
167 |
return 3;
|
135 |
168 |
}
|
136 |
169 |
|
137 |
170 |
static inline int
|
138 |
171 |
bgp_put_attr_hdr4(byte *buf, uint code, uint flags, uint len)
|
139 |
172 |
{
|
140 |
|
*buf++ = flags | BAF_EXT_LEN;
|
141 |
|
*buf++ = code;
|
142 |
|
put_u16(buf, len);
|
143 |
|
return 4;
|
|
173 |
*buf++ = flags | BAF_EXT_LEN;
|
|
174 |
*buf++ = code;
|
|
175 |
put_u16(buf, len);
|
|
176 |
return 4;
|
144 |
177 |
}
|
145 |
178 |
|
146 |
179 |
static inline int
|
147 |
180 |
bgp_put_attr_hdr(byte *buf, uint code, uint flags, uint len)
|
148 |
181 |
{
|
149 |
|
if (len < 256)
|
150 |
|
return bgp_put_attr_hdr3(buf, code, flags, len);
|
151 |
|
else
|
152 |
|
return bgp_put_attr_hdr4(buf, code, flags, len);
|
|
182 |
if (len < 256)
|
|
183 |
return bgp_put_attr_hdr3(buf, code, flags, len);
|
|
184 |
else
|
|
185 |
return bgp_put_attr_hdr4(buf, code, flags, len);
|
153 |
186 |
}
|
154 |
187 |
|
155 |
188 |
static int
|
156 |
189 |
bgp_encode_u8(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
|
157 |
190 |
{
|
158 |
|
if (size < (3+1))
|
159 |
|
return -1;
|
|
191 |
if (size < (3+1))
|
|
192 |
return -1;
|
160 |
193 |
|
161 |
|
bgp_put_attr_hdr3(buf, EA_ID(a->id), a->flags, 1);
|
162 |
|
buf[3] = a->u.data;
|
|
194 |
bgp_put_attr_hdr3(buf, EA_ID(a->id), a->flags, 1);
|
|
195 |
buf[3] = a->u.data;
|
163 |
196 |
|
164 |
|
return 3+1;
|
|
197 |
return 3+1;
|
165 |
198 |
}
|
166 |
199 |
|
167 |
200 |
static int
|
168 |
201 |
bgp_encode_u32(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
|
169 |
202 |
{
|
170 |
|
if (size < (3+4))
|
171 |
|
return -1;
|
|
203 |
if (size < (3+4))
|
|
204 |
return -1;
|
172 |
205 |
|
173 |
|
bgp_put_attr_hdr3(buf, EA_ID(a->id), a->flags, 4);
|
174 |
|
put_u32(buf+3, a->u.data);
|
|
206 |
bgp_put_attr_hdr3(buf, EA_ID(a->id), a->flags, 4);
|
|
207 |
put_u32(buf+3, a->u.data);
|
175 |
208 |
|
176 |
|
return 3+4;
|
|
209 |
return 3+4;
|
177 |
210 |
}
|
178 |
211 |
|
179 |
212 |
static int
|
180 |
213 |
bgp_encode_u32s(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
|
181 |
214 |
{
|
182 |
|
uint len = a->u.ptr->length;
|
|
215 |
uint len = a->u.ptr->length;
|
183 |
216 |
|
184 |
|
if (size < (4+len))
|
185 |
|
return -1;
|
|
217 |
if (size < (4+len))
|
|
218 |
return -1;
|
186 |
219 |
|
187 |
|
uint hdr = bgp_put_attr_hdr(buf, EA_ID(a->id), a->flags, len);
|
188 |
|
put_u32s(buf + hdr, (u32 *) a->u.ptr->data, len / 4);
|
|
220 |
uint hdr = bgp_put_attr_hdr(buf, EA_ID(a->id), a->flags, len);
|
|
221 |
put_u32s(buf + hdr, (u32 *) a->u.ptr->data, len / 4);
|
189 |
222 |
|
190 |
|
return hdr + len;
|
|
223 |
return hdr + len;
|
191 |
224 |
}
|
192 |
225 |
|
193 |
226 |
static int
|
194 |
227 |
bgp_put_attr(byte *buf, uint size, uint code, uint flags, byte *data, uint len)
|
195 |
228 |
{
|
196 |
|
if (size < (4+len))
|
197 |
|
return -1;
|
|
229 |
if (size < (4+len))
|
|
230 |
return -1;
|
198 |
231 |
|
199 |
|
uint hdr = bgp_put_attr_hdr(buf, code, flags, len);
|
200 |
|
memcpy(buf + hdr, data, len);
|
|
232 |
uint hdr = bgp_put_attr_hdr(buf, code, flags, len);
|
|
233 |
memcpy(buf + hdr, data, len);
|
201 |
234 |
|
202 |
|
return hdr + len;
|
|
235 |
return hdr + len;
|
203 |
236 |
}
|
204 |
237 |
|
205 |
238 |
static int
|
206 |
239 |
bgp_encode_raw(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
|
207 |
240 |
{
|
208 |
|
return bgp_put_attr(buf, size, EA_ID(a->id), a->flags, a->u.ptr->data, a->u.ptr->length);
|
|
241 |
return bgp_put_attr(buf, size, EA_ID(a->id), a->flags, a->u.ptr->data, a->u.ptr->length);
|
209 |
242 |
}
|
210 |
243 |
|
211 |
244 |
|
... | ... | |
216 |
249 |
static void
|
217 |
250 |
bgp_export_origin(struct bgp_export_state *s, eattr *a)
|
218 |
251 |
{
|
219 |
|
if (a->u.data > 2)
|
220 |
|
WITHDRAW(BAD_VALUE, "ORIGIN", a->u.data);
|
|
252 |
if (a->u.data > 2)
|
|
253 |
WITHDRAW(BAD_VALUE, "ORIGIN", a->u.data);
|
221 |
254 |
}
|
222 |
255 |
|
223 |
256 |
static void
|
224 |
257 |
bgp_decode_origin(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
225 |
258 |
{
|
226 |
|
if (len != 1)
|
227 |
|
WITHDRAW(BAD_LENGTH, "ORIGIN", len);
|
|
259 |
if (len != 1)
|
|
260 |
WITHDRAW(BAD_LENGTH, "ORIGIN", len);
|
228 |
261 |
|
229 |
|
if (data[0] > 2)
|
230 |
|
WITHDRAW(BAD_VALUE, "ORIGIN", data[0]);
|
|
262 |
if (data[0] > 2)
|
|
263 |
WITHDRAW(BAD_VALUE, "ORIGIN", data[0]);
|
231 |
264 |
|
232 |
|
bgp_set_attr_u32(to, s->pool, BA_ORIGIN, flags, data[0]);
|
|
265 |
bgp_set_attr_u32(to, s->pool, BA_ORIGIN, flags, data[0]);
|
233 |
266 |
}
|
234 |
267 |
|
235 |
268 |
static void
|
236 |
269 |
bgp_format_origin(eattr *a, byte *buf, uint size UNUSED)
|
237 |
270 |
{
|
238 |
|
static const char *bgp_origin_names[] = { "IGP", "EGP", "Incomplete" };
|
|
271 |
static const char *bgp_origin_names[] = { "IGP", "EGP", "Incomplete" };
|
239 |
272 |
|
240 |
|
bsprintf(buf, (a->u.data <= 2) ? bgp_origin_names[a->u.data] : "?");
|
|
273 |
bsprintf(buf, (a->u.data <= 2) ? bgp_origin_names[a->u.data] : "?");
|
241 |
274 |
}
|
242 |
275 |
|
243 |
276 |
|
244 |
277 |
static int
|
245 |
278 |
bgp_encode_as_path(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
|
246 |
279 |
{
|
247 |
|
byte *data = a->u.ptr->data;
|
248 |
|
uint len = a->u.ptr->length;
|
|
280 |
byte *data = a->u.ptr->data;
|
|
281 |
uint len = a->u.ptr->length;
|
|
282 |
|
|
283 |
if (!s->as4_session)
|
|
284 |
{
|
|
285 |
/* Prepare 16-bit AS_PATH (from 32-bit one) in a temporary buffer */
|
|
286 |
byte *src = data;
|
|
287 |
data = alloca(len);
|
|
288 |
len = as_path_32to16(data, src, len);
|
|
289 |
}
|
|
290 |
|
|
291 |
return bgp_put_attr(buf, size, BA_AS_PATH, a->flags, data, len);
|
|
292 |
}
|
|
293 |
|
|
294 |
static int
|
|
295 |
bgp_encode_nhs_list(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
|
|
296 |
{
|
|
297 |
byte *data = a->u.ptr->data;
|
|
298 |
uint len = a->u.ptr->length;
|
249 |
299 |
|
250 |
|
if (!s->as4_session)
|
251 |
|
{
|
252 |
|
/* Prepare 16-bit AS_PATH (from 32-bit one) in a temporary buffer */
|
253 |
|
byte *src = data;
|
254 |
|
data = alloca(len);
|
255 |
|
len = as_path_32to16(data, src, len);
|
256 |
|
}
|
|
300 |
if (!s->as4_session)
|
|
301 |
{
|
|
302 |
/* Prepare 16-bit AS_PATH (from 32-bit one) in a temporary buffer */
|
|
303 |
byte *src = data;
|
|
304 |
data = alloca(len);
|
|
305 |
len = as_path_32to16(data, src, len);
|
|
306 |
}
|
257 |
307 |
|
258 |
|
return bgp_put_attr(buf, size, BA_AS_PATH, a->flags, data, len);
|
|
308 |
return bgp_put_attr(buf, size, BA_AS_NH_LIST, a->flags, data, len);
|
259 |
309 |
}
|
260 |
310 |
|
|
311 |
/**
|
|
312 |
* Function to encode the load to the correct attribute
|
|
313 |
* @param s bgp write state
|
|
314 |
* @param a attribute
|
|
315 |
* @param buf buffer
|
|
316 |
* @param size size of the attribute
|
|
317 |
* @return
|
|
318 |
*/
|
|
319 |
static int
|
|
320 |
bgp_encode_as_load(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
|
|
321 |
{
|
|
322 |
//Pointer to the data contained in the attribute
|
|
323 |
byte *data = a->u.ptr->data;
|
|
324 |
//Actual length of the attribute data
|
|
325 |
uint len = a->u.ptr->length;
|
|
326 |
|
|
327 |
if (!s->as4_session)
|
|
328 |
{
|
|
329 |
// Prepare 16-bit AS_PATH (from 32-bit one) in a temporary buffer
|
|
330 |
byte *src = data;
|
|
331 |
data = alloca(len);
|
|
332 |
len = as_path_32to16(data, src, len);
|
|
333 |
}
|
|
334 |
|
|
335 |
return bgp_put_attr(buf, size, BA_AS_LOAD, a->flags, data, len);
|
|
336 |
}
|
|
337 |
|
|
338 |
/**
|
|
339 |
* Function to decode the as path passed from the packet
|
|
340 |
* @param s
|
|
341 |
* @param code
|
|
342 |
* @param flags
|
|
343 |
* @param data
|
|
344 |
* @param len
|
|
345 |
* @param to
|
|
346 |
*/
|
261 |
347 |
static void
|
262 |
348 |
bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
263 |
349 |
{
|
264 |
|
struct bgp_proto *p = s->proto;
|
265 |
|
int as_length = s->as4_session ? 4 : 2;
|
266 |
|
int as_confed = p->cf->confederation && p->is_interior;
|
267 |
|
char err[128];
|
|
350 |
struct bgp_proto *p = s->proto;
|
|
351 |
int as_length = s->as4_session ? 4 : 2;
|
|
352 |
int as_confed = p->cf->confederation && p->is_interior;
|
|
353 |
char err[128];
|
268 |
354 |
|
269 |
|
if (!as_path_valid(data, len, as_length, as_confed, err, sizeof(err)))
|
270 |
|
WITHDRAW("Malformed AS_PATH attribute - %s", err);
|
|
355 |
//Catch malformed attribute
|
|
356 |
if (!as_path_valid(data, len, as_length, as_confed, err, sizeof(err)))
|
|
357 |
WITHDRAW("Malformed AS_PATH attribute - %s", err);
|
271 |
358 |
|
272 |
|
/* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
|
273 |
|
if (p->is_interior && !p->is_internal &&
|
274 |
|
((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
|
275 |
|
WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
|
|
359 |
/* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
|
|
360 |
if (p->is_interior && !p->is_internal &&
|
|
361 |
((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
|
|
362 |
WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
|
276 |
363 |
|
277 |
|
if (!s->as4_session)
|
278 |
|
{
|
279 |
|
/* Prepare 32-bit AS_PATH (from 16-bit one) in a temporary buffer */
|
280 |
|
byte *src = data;
|
281 |
|
data = alloca(2*len);
|
282 |
|
len = as_path_16to32(data, src, len);
|
283 |
|
}
|
|
364 |
if (!s->as4_session)
|
|
365 |
{
|
|
366 |
/* Prepare 32-bit AS_PATH (from 16-bit one) in a temporary buffer */
|
|
367 |
byte *src = data;
|
|
368 |
data = alloca(2*len);
|
|
369 |
len = as_path_16to32(data, src, len);
|
|
370 |
}
|
|
371 |
char buf2[32];
|
|
372 |
sprintf(buf2, "%02X%02X%02X%02X",data[2], data[3], data[4], data[5]);
|
|
373 |
//TODO this data cannot be taken from the attribute data?
|
|
374 |
ASRicezione = (int)strtol(buf2, NULL, 16);
|
|
375 |
//log(L_INFO "%d", ASRicezione);
|
|
376 |
bgp_set_attr_data(to, s->pool, BA_AS_PATH, flags, data, len);
|
|
377 |
}
|
|
378 |
|
|
379 |
/**
|
|
380 |
* Function used to decode the list of NHs take from the packet
|
|
381 |
* @param s
|
|
382 |
* @param code
|
|
383 |
* @param flags
|
|
384 |
* @param data
|
|
385 |
* @param len
|
|
386 |
* @param to
|
|
387 |
*/
|
|
388 |
static void
|
|
389 |
bgp_decode_nhs_list(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
|
390 |
{
|
|
391 |
struct bgp_proto *p = s->proto;
|
|
392 |
int as_length = s->as4_session ? 4 : 2;
|
|
393 |
int as_confed = p->cf->confederation && p->is_interior;
|
|
394 |
char err[128];
|
|
395 |
|
|
396 |
if (!as_path_valid(data, len, as_length, as_confed, err, sizeof(err)))
|
|
397 |
WITHDRAW("Malformed AS_PATH attribute - %s", err);
|
|
398 |
|
|
399 |
/* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
|
|
400 |
if (p->is_interior && !p->is_internal &&
|
|
401 |
((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
|
|
402 |
WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
|
284 |
403 |
|
285 |
|
bgp_set_attr_data(to, s->pool, BA_AS_PATH, flags, data, len);
|
|
404 |
if (!s->as4_session)
|
|
405 |
{
|
|
406 |
/* Prepare 32-bit AS_PATH (from 16-bit one) in a temporary buffer */
|
|
407 |
byte *src = data;
|
|
408 |
data = alloca(2*len);
|
|
409 |
len = as_path_16to32(data, src, len);
|
|
410 |
}
|
|
411 |
|
|
412 |
//log(L_INFO "Len: %d", len);
|
|
413 |
if(len > 0){
|
|
414 |
numeroNHarrivati = data[1];
|
|
415 |
//log(L_INFO "Decodifica nh %d:", numeroNHarrivati);
|
|
416 |
int i = 0;
|
|
417 |
int k = 2;
|
|
418 |
/* Check if my as is in the NH list */
|
|
419 |
for(i = 0;i < data[1]; i++){
|
|
420 |
/*log(L_INFO "C'è un NH");
|
|
421 |
*log(L_INFO "data[%d] = %d",i, data[k]);
|
|
422 |
*log(L_INFO "data[%d] = %d",i, data[k+1]);
|
|
423 |
*log(L_INFO "data[%d] = %d",i, data[k+2]);
|
|
424 |
*log(L_INFO "data[%d] = %d",i, data[k+3]);
|
|
425 |
*/
|
|
426 |
char buf2[32];
|
|
427 |
sprintf(buf2, "%02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);
|
|
428 |
unsigned int nhLetto = (int)strtol(buf2, NULL, 16);
|
|
429 |
//log(L_INFO "nh[%d] = %d",i, nhLetto);
|
|
430 |
k+=4;
|
|
431 |
if(p->public_as == nhLetto){
|
|
432 |
//log(L_INFO "Hey io sono il NH");
|
|
433 |
//I founded that I am in the nh list
|
|
434 |
sonoIlNH = 1;
|
|
435 |
}
|
|
436 |
}
|
|
437 |
}
|
286 |
438 |
}
|
287 |
439 |
|
|
440 |
/**
|
|
441 |
* Function to decode the load data structure from an update packet
|
|
442 |
* @param s
|
|
443 |
* @param code
|
|
444 |
* @param flags
|
|
445 |
* @param data
|
|
446 |
* @param len
|
|
447 |
* @param to
|
|
448 |
*/
|
|
449 |
static void
|
|
450 |
bgp_decode_as_load(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
|
451 |
{
|
|
452 |
//log(L_INFO "SONO IN AS LOAD");
|
|
453 |
struct bgp_proto *p = s->proto;
|
|
454 |
int as_length = s->as4_session ? 4 : 2;
|
|
455 |
int as_confed = p->cf->confederation && p->is_interior;
|
|
456 |
char err[128];
|
|
457 |
|
|
458 |
if (!as_path_valid(data, len, as_length, as_confed, err, sizeof(err)))
|
|
459 |
WITHDRAW("Malformed AS_LOAD attribute - %s", err);
|
288 |
460 |
|
|
461 |
// In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0
|
|
462 |
if (p->is_interior && !p->is_internal &&
|
|
463 |
((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
|
|
464 |
WITHDRAW("Malformed AS_LOAD attribute - %s", "missing initial AS_CONFED_SEQUENCE");
|
|
465 |
|
|
466 |
if (!s->as4_session)
|
|
467 |
{
|
|
468 |
// Prepare 32-bit AS_PATH (from 16-bit one) in a temporary buffer
|
|
469 |
byte *src = data;
|
|
470 |
data = alloca(2*len);
|
|
471 |
len = as_path_16to32(data, src, len);
|
|
472 |
}
|
|
473 |
|
|
474 |
//log(L_INFO "Len: %d", len);
|
|
475 |
if(len > 0){
|
|
476 |
//log(L_INFO "Decodifica nh %d:", data[1]);
|
|
477 |
int i = 0;
|
|
478 |
int k = 2;
|
|
479 |
for(i = 0;i < data[1]; i++){
|
|
480 |
/*log(L_INFO "C'è un AS");
|
|
481 |
log(L_INFO "data[%d] = %d",i, data[k]);
|
|
482 |
log(L_INFO "data[%d] = %d",i, data[k+1]);
|
|
483 |
log(L_INFO "data[%d] = %d",i, data[k+2]);
|
|
484 |
log(L_INFO "data[%d] = %d",i, data[k+3]);
|
|
485 |
log(L_INFO "AS => %02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);*/
|
|
486 |
char buf2[32];
|
|
487 |
sprintf(buf2, "%02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);
|
|
488 |
unsigned int asLetto = (int)strtol(buf2, NULL, 16);
|
|
489 |
//log(L_INFO "as[%d] = %d",i, asLetto);
|
|
490 |
k+=4;
|
|
491 |
i++;
|
|
492 |
/*log(L_INFO "Load AS");
|
|
493 |
log(L_INFO "data[%d] = %d",i, data[k]);
|
|
494 |
log(L_INFO "data[%d] = %d",i, data[k+1]);
|
|
495 |
log(L_INFO "data[%d] = %d",i, data[k+2]);
|
|
496 |
log(L_INFO "data[%d] = %d",i, data[k+3]);
|
|
497 |
log(L_INFO "AS LOAD => %02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);*/
|
|
498 |
sprintf(buf2, "%02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);
|
|
499 |
int loadLetto = (int)strtol(buf2, NULL, 16);
|
|
500 |
float loadASRileato = *((float *) &loadLetto);
|
|
501 |
char output[50];
|
|
502 |
snprintf(output, 50, "%f", loadASRileato);
|
|
503 |
//log(L_INFO "load[%d] = %s",i, output);
|
|
504 |
k+=4;
|
|
505 |
i++;
|
|
506 |
|
|
507 |
/*log(L_INFO "Metrica Load AS");
|
|
508 |
log(L_INFO "data[%d] = %d",i, data[k]);
|
|
509 |
log(L_INFO "data[%d] = %d",i, data[k+1]);
|
|
510 |
log(L_INFO "data[%d] = %d",i, data[k+2]);
|
|
511 |
log(L_INFO "data[%d] = %d",i, data[k+3]);
|
|
512 |
log(L_INFO "AS METRIC => %02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);*/
|
|
513 |
sprintf(buf2, "%02X%02X%02X%02X",data[k], data[k+1], data[k+2], data[k+3]);
|
|
514 |
int metrica = (int)strtol(buf2, NULL, 16);
|
|
515 |
//log(L_INFO "metrica[%d] = %d",i, metrica);
|
|
516 |
k+=4;
|
|
517 |
|
|
518 |
char chKeyASLoad[12] = "";
|
|
519 |
sprintf(chKeyASLoad, "%d", asLetto);
|
|
520 |
|
|
521 |
//Generate an ASLoad element from the data get in this section of the packet
|
|
522 |
ASLoad ASLoad_ricevuto = {loadASRileato, metrica, 1, NULL};
|
|
523 |
map_init(&ASLoad_ricevuto.remoteMap);
|
|
524 |
|
|
525 |
//Check if it's already in the data structure
|
|
526 |
ASLoad *ASLoad_element = map_get(&ASLoad_map, chKeyASLoad);
|
|
527 |
if (ASLoad_element) {
|
|
528 |
//log(L_INFO "AS già presente, aggiorno il valore");
|
|
529 |
if(asLetto != p->public_as && ASLoad_element->metrica < ASLoad_ricevuto.metrica){
|
|
530 |
ASLoad_element->load = ASLoad_ricevuto.load;
|
|
531 |
ASLoad_element->metrica = ASLoad_ricevuto.metrica;
|
|
532 |
//ASLoad_element->changed = 1;
|
|
533 |
|
|
534 |
//Clean the remote map
|
|
535 |
const char *key;
|
|
536 |
map_iter_t iter = map_iter(&ASLoad_element->remoteMap);
|
|
537 |
while ((key = map_next(&ASLoad_element->remoteMap, &iter))) {
|
|
538 |
map_remove(&ASLoad_element->remoteMap, key);
|
|
539 |
}
|
|
540 |
}
|
|
541 |
if(asLetto == p->public_as && ASLoad_element->metrica < ASLoad_ricevuto.metrica){
|
|
542 |
ASLoad_element->metrica = ASLoad_ricevuto.metrica++;
|
|
543 |
//ASLoad_element->changed = 1;
|
|
544 |
const char *key;
|
|
545 |
map_iter_t iter = map_iter(&ASLoad_element->remoteMap);
|
|
546 |
|
|
547 |
while ((key = map_next(&ASLoad_element->remoteMap, &iter))) {
|
|
548 |
map_remove(&ASLoad_element->remoteMap, key);
|
|
549 |
}
|
|
550 |
}
|
|
551 |
} else {
|
|
552 |
//log(L_INFO "AS non presente, lo aggiungo");
|
|
553 |
map_set(&ASLoad_map, chKeyASLoad, ASLoad_ricevuto);
|
|
554 |
}
|
|
555 |
}
|
|
556 |
}
|
|
557 |
}
|
|
558 |
|
|
559 |
/**
|
|
560 |
* Function to encode the NH
|
|
561 |
* @param s
|
|
562 |
* @param a
|
|
563 |
* @param buf
|
|
564 |
* @param size
|
|
565 |
* @return
|
|
566 |
*/
|
289 |
567 |
static int
|
290 |
568 |
bgp_encode_next_hop(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
|
291 |
569 |
{
|
292 |
|
/*
|
293 |
|
* The NEXT_HOP attribute is used only in traditional (IPv4) BGP. In MP-BGP,
|
294 |
|
* the next hop is encoded as a part of the MP_REACH_NLRI attribute, so we
|
295 |
|
* store it and encode it later by AFI-specific hooks.
|
296 |
|
*/
|
|
570 |
/*
|
|
571 |
* The NEXT_HOP attribute is used only in traditional (IPv4) BGP. In MP-BGP,
|
|
572 |
* the next hop is encoded as a part of the MP_REACH_NLRI attribute, so we
|
|
573 |
* store it and encode it later by AFI-specific hooks.
|
|
574 |
*/
|
297 |
575 |
|
298 |
|
if (s->channel->afi == BGP_AF_IPV4)
|
299 |
|
{
|
300 |
|
ASSERT(a->u.ptr->length == sizeof(ip_addr));
|
|
576 |
if (s->channel->afi == BGP_AF_IPV4)
|
|
577 |
{
|
|
578 |
ASSERT(a->u.ptr->length == sizeof(ip_addr));
|
301 |
579 |
|
302 |
|
if (size < (3+4))
|
303 |
|
return -1;
|
|
580 |
if (size < (3+4))
|
|
581 |
return -1;
|
304 |
582 |
|
305 |
|
bgp_put_attr_hdr3(buf, BA_NEXT_HOP, a->flags, 4);
|
306 |
|
put_ip4(buf+3, ipa_to_ip4( *(ip_addr *) a->u.ptr->data ));
|
|
583 |
bgp_put_attr_hdr3(buf, BA_NEXT_HOP, a->flags, 4);
|
|
584 |
put_ip4(buf+3, ipa_to_ip4( *(ip_addr *) a->u.ptr->data ));
|
307 |
585 |
|
308 |
|
return 3+4;
|
309 |
|
}
|
310 |
|
else
|
311 |
|
{
|
312 |
|
s->mp_next_hop = a;
|
313 |
|
return 0;
|
314 |
|
}
|
|
586 |
return 3+4;
|
|
587 |
}
|
|
588 |
else
|
|
589 |
{
|
|
590 |
s->mp_next_hop = a;
|
|
591 |
return 0;
|
|
592 |
}
|
315 |
593 |
}
|
316 |
594 |
|
317 |
595 |
static void
|
318 |
596 |
bgp_decode_next_hop(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUSED, byte *data, uint len, ea_list **to UNUSED)
|
319 |
597 |
{
|
320 |
|
if (len != 4)
|
321 |
|
WITHDRAW(BAD_LENGTH, "NEXT_HOP", len);
|
|
598 |
if (len != 4)
|
|
599 |
WITHDRAW(BAD_LENGTH, "NEXT_HOP", len);
|
322 |
600 |
|
323 |
|
/* Semantic checks are done later */
|
324 |
|
s->ip_next_hop_len = len;
|
325 |
|
s->ip_next_hop_data = data;
|
|
601 |
nhKey = 0;
|
|
602 |
nhKey += data[0] + data[1] + data[2] + data[3];
|
|
603 |
|
|
604 |
/* Semantic checks are done later */
|
|
605 |
s->ip_next_hop_len = len;
|
|
606 |
s->ip_next_hop_data = data;
|
326 |
607 |
}
|
327 |
608 |
|
328 |
|
/* TODO: This function should use AF-specific hook */
|
329 |
609 |
static void
|
330 |
610 |
bgp_format_next_hop(eattr *a, byte *buf, uint size UNUSED)
|
331 |
611 |
{
|
332 |
|
ip_addr *nh = (void *) a->u.ptr->data;
|
333 |
|
uint len = a->u.ptr->length;
|
|
612 |
ip_addr *nh = (void *) a->u.ptr->data;
|
|
613 |
uint len = a->u.ptr->length;
|
334 |
614 |
|
335 |
|
ASSERT((len == 16) || (len == 32));
|
|
615 |
ASSERT((len == 16) || (len == 32));
|
336 |
616 |
|
337 |
|
/* in IPv6, we may have two addresses in NEXT HOP */
|
338 |
|
if ((len == 16) || ipa_zero(nh[1]))
|
339 |
|
bsprintf(buf, "%I", nh[0]);
|
340 |
|
else
|
341 |
|
bsprintf(buf, "%I %I", nh[0], nh[1]);
|
|
617 |
/* in IPv6, we may have two addresses in NEXT HOP */
|
|
618 |
if ((len == 16) || ipa_zero(nh[1]))
|
|
619 |
bsprintf(buf, "%I", nh[0]);
|
|
620 |
else
|
|
621 |
bsprintf(buf, "%I %I", nh[0], nh[1]);
|
342 |
622 |
}
|
343 |
623 |
|
344 |
624 |
|
345 |
625 |
static void
|
346 |
626 |
bgp_decode_med(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
347 |
627 |
{
|
348 |
|
if (len != 4)
|
349 |
|
WITHDRAW(BAD_LENGTH, "MULTI_EXIT_DISC", len);
|
|
628 |
if (len != 4)
|
|
629 |
WITHDRAW(BAD_LENGTH, "MULTI_EXIT_DISC", len);
|
350 |
630 |
|
351 |
|
u32 val = get_u32(data);
|
352 |
|
bgp_set_attr_u32(to, s->pool, BA_MULTI_EXIT_DISC, flags, val);
|
|
631 |
u32 val = get_u32(data);
|
|
632 |
bgp_set_attr_u32(to, s->pool, BA_MULTI_EXIT_DISC, flags, val);
|
353 |
633 |
}
|
354 |
634 |
|
|
635 |
//TODO hard todo, use atributes and not variables for those things
|
|
636 |
/**
|
|
637 |
* Function to decode the load_out in a packet
|
|
638 |
* @param s
|
|
639 |
* @param code
|
|
640 |
* @param flags
|
|
641 |
* @param data
|
|
642 |
* @param len
|
|
643 |
* @param to
|
|
644 |
*/
|
|
645 |
static void
|
|
646 |
bgp_decode_load_out(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
|
647 |
{
|
|
648 |
if (len != 4)
|
|
649 |
WITHDRAW(BAD_LENGTH, "BA_LOAD_SENDER", len);
|
|
650 |
|
|
651 |
u32 val = get_u32(data);
|
|
652 |
char output[50];
|
|
653 |
int v = val;
|
|
654 |
loadOutRilevato = *((float *) &v);
|
|
655 |
snprintf(output, 50, "%f", loadOutRilevato);
|
|
656 |
}
|
355 |
657 |
|
356 |
658 |
static void
|
357 |
659 |
bgp_export_local_pref(struct bgp_export_state *s, eattr *a)
|
358 |
660 |
{
|
359 |
|
if (!s->proto->is_interior && !s->proto->cf->allow_local_pref)
|
360 |
|
UNSET(a);
|
|
661 |
if (!s->proto->is_interior && !s->proto->cf->allow_local_pref)
|
|
662 |
UNSET(a);
|
361 |
663 |
}
|
362 |
664 |
|
363 |
665 |
static void
|
364 |
666 |
bgp_decode_local_pref(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
365 |
667 |
{
|
366 |
|
if (!s->proto->is_interior && !s->proto->cf->allow_local_pref)
|
367 |
|
DISCARD(BAD_EBGP, "LOCAL_PREF");
|
|
668 |
if (!s->proto->is_interior && !s->proto->cf->allow_local_pref)
|
|
669 |
DISCARD(BAD_EBGP, "LOCAL_PREF");
|
368 |
670 |
|
369 |
|
if (len != 4)
|
370 |
|
WITHDRAW(BAD_LENGTH, "LOCAL_PREF", len);
|
|
671 |
if (len != 4)
|
|
672 |
WITHDRAW(BAD_LENGTH, "LOCAL_PREF", len);
|
371 |
673 |
|
372 |
|
u32 val = get_u32(data);
|
373 |
|
bgp_set_attr_u32(to, s->pool, BA_LOCAL_PREF, flags, val);
|
|
674 |
u32 val = get_u32(data);
|
|
675 |
bgp_set_attr_u32(to, s->pool, BA_LOCAL_PREF, flags, val);
|
374 |
676 |
}
|
375 |
677 |
|
376 |
678 |
|
377 |
679 |
static void
|
378 |
680 |
bgp_decode_atomic_aggr(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data UNUSED, uint len, ea_list **to)
|
379 |
681 |
{
|
380 |
|
if (len != 0)
|
381 |
|
DISCARD(BAD_LENGTH, "ATOMIC_AGGR", len);
|
|
682 |
if (len != 0)
|
|
683 |
DISCARD(BAD_LENGTH, "ATOMIC_AGGR", len);
|
382 |
684 |
|
383 |
|
bgp_set_attr_data(to, s->pool, BA_ATOMIC_AGGR, flags, NULL, 0);
|
|
685 |
bgp_set_attr_data(to, s->pool, BA_ATOMIC_AGGR, flags, NULL, 0);
|
384 |
686 |
}
|
385 |
687 |
|
386 |
688 |
static int
|
387 |
689 |
bgp_encode_aggregator(struct bgp_write_state *s, eattr *a, byte *buf, uint size)
|
388 |
690 |
{
|
389 |
|
byte *data = a->u.ptr->data;
|
390 |
|
uint len = a->u.ptr->length;
|
|
691 |
byte *data = a->u.ptr->data;
|
|
692 |
uint len = a->u.ptr->length;
|
391 |
693 |
|
392 |
|
if (!s->as4_session)
|
393 |
|
{
|
394 |
|
/* Prepare 16-bit AGGREGATOR (from 32-bit one) in a temporary buffer */
|
395 |
|
byte *src = data;
|
396 |
|
data = alloca(6);
|
397 |
|
len = aggregator_32to16(data, src);
|
398 |
|
}
|
|
694 |
if (!s->as4_session)
|
|
695 |
{
|
|
696 |
/* Prepare 16-bit AGGREGATOR (from 32-bit one) in a temporary buffer */
|
|
697 |
byte *src = data;
|
|
698 |
data = alloca(6);
|
|
699 |
len = aggregator_32to16(data, src);
|
|
700 |
}
|
399 |
701 |
|
400 |
|
return bgp_put_attr(buf, size, BA_AGGREGATOR, a->flags, data, len);
|
|
702 |
return bgp_put_attr(buf, size, BA_AGGREGATOR, a->flags, data, len);
|
401 |
703 |
}
|
402 |
704 |
|
403 |
705 |
static void
|
404 |
706 |
bgp_decode_aggregator(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
405 |
707 |
{
|
406 |
|
if (len != (s->as4_session ? 8 : 6))
|
407 |
|
DISCARD(BAD_LENGTH, "AGGREGATOR", len);
|
|
708 |
if (len != (s->as4_session ? 8 : 6))
|
|
709 |
DISCARD(BAD_LENGTH, "AGGREGATOR", len);
|
408 |
710 |
|
409 |
|
if (!s->as4_session)
|
410 |
|
{
|
411 |
|
/* Prepare 32-bit AGGREGATOR (from 16-bit one) in a temporary buffer */
|
412 |
|
byte *src = data;
|
413 |
|
data = alloca(8);
|
414 |
|
len = aggregator_16to32(data, src);
|
415 |
|
}
|
|
711 |
if (!s->as4_session)
|
|
712 |
{
|
|
713 |
/* Prepare 32-bit AGGREGATOR (from 16-bit one) in a temporary buffer */
|
|
714 |
byte *src = data;
|
|
715 |
data = alloca(8);
|
|
716 |
len = aggregator_16to32(data, src);
|
|
717 |
}
|
416 |
718 |
|
417 |
|
bgp_set_attr_data(to, s->pool, BA_AGGREGATOR, flags, data, len);
|
|
719 |
bgp_set_attr_data(to, s->pool, BA_AGGREGATOR, flags, data, len);
|
418 |
720 |
}
|
419 |
721 |
|
420 |
722 |
static void
|
421 |
723 |
bgp_format_aggregator(eattr *a, byte *buf, uint size UNUSED)
|
422 |
724 |
{
|
423 |
|
byte *data = a->u.ptr->data;
|
|
725 |
byte *data = a->u.ptr->data;
|
424 |
726 |
|
425 |
|
bsprintf(buf, "%I4 AS%u", get_ip4(data+4), get_u32(data+0));
|
|
727 |
bsprintf(buf, "%I4 AS%u", get_ip4(data+4), get_u32(data+0));
|
426 |
728 |
}
|
427 |
729 |
|
428 |
730 |
|
429 |
731 |
static void
|
430 |
732 |
bgp_export_community(struct bgp_export_state *s, eattr *a)
|
431 |
733 |
{
|
432 |
|
if (a->u.ptr->length == 0)
|
433 |
|
UNSET(a);
|
|
734 |
if (a->u.ptr->length == 0)
|
|
735 |
UNSET(a);
|
434 |
736 |
|
435 |
|
a->u.ptr = int_set_sort(s->pool, a->u.ptr);
|
|
737 |
a->u.ptr = int_set_sort(s->pool, a->u.ptr);
|
436 |
738 |
}
|
437 |
739 |
|
438 |
740 |
static void
|
439 |
741 |
bgp_decode_community(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
440 |
742 |
{
|
441 |
|
if (!len || (len % 4))
|
442 |
|
WITHDRAW(BAD_LENGTH, "COMMUNITY", len);
|
|
743 |
if (!len || (len % 4))
|
|
744 |
WITHDRAW(BAD_LENGTH, "COMMUNITY", len);
|
443 |
745 |
|
444 |
|
struct adata *ad = lp_alloc_adata(s->pool, len);
|
445 |
|
get_u32s(data, (u32 *) ad->data, len / 4);
|
446 |
|
bgp_set_attr_ptr(to, s->pool, BA_COMMUNITY, flags, ad);
|
|
746 |
struct adata *ad = lp_alloc_adata(s->pool, len);
|
|
747 |
get_u32s(data, (u32 *) ad->data, len / 4);
|
|
748 |
bgp_set_attr_ptr(to, s->pool, BA_COMMUNITY, flags, ad);
|
447 |
749 |
}
|
448 |
750 |
|
449 |
751 |
|
450 |
752 |
static void
|
451 |
753 |
bgp_export_originator_id(struct bgp_export_state *s, eattr *a)
|
452 |
754 |
{
|
453 |
|
if (!s->proto->is_internal)
|
454 |
|
UNSET(a);
|
|
755 |
if (!s->proto->is_internal)
|
|
756 |
UNSET(a);
|
455 |
757 |
}
|
456 |
758 |
|
457 |
759 |
static void
|
458 |
760 |
bgp_decode_originator_id(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
459 |
761 |
{
|
460 |
|
if (!s->proto->is_internal)
|
461 |
|
DISCARD(BAD_EBGP, "ORIGINATOR_ID");
|
|
762 |
if (!s->proto->is_internal)
|
|
763 |
DISCARD(BAD_EBGP, "ORIGINATOR_ID");
|
462 |
764 |
|
463 |
|
if (len != 4)
|
464 |
|
WITHDRAW(BAD_LENGTH, "ORIGINATOR_ID", len);
|
|
765 |
if (len != 4)
|
|
766 |
WITHDRAW(BAD_LENGTH, "ORIGINATOR_ID", len);
|
465 |
767 |
|
466 |
|
u32 val = get_u32(data);
|
467 |
|
bgp_set_attr_u32(to, s->pool, BA_ORIGINATOR_ID, flags, val);
|
|
768 |
u32 val = get_u32(data);
|
|
769 |
bgp_set_attr_u32(to, s->pool, BA_ORIGINATOR_ID, flags, val);
|
468 |
770 |
}
|
469 |
771 |
|
470 |
772 |
|
471 |
773 |
static void
|
472 |
774 |
bgp_export_cluster_list(struct bgp_export_state *s UNUSED, eattr *a)
|
473 |
775 |
{
|
474 |
|
if (!s->proto->is_internal)
|
475 |
|
UNSET(a);
|
|
776 |
if (!s->proto->is_internal)
|
|
777 |
UNSET(a);
|
476 |
778 |
|
477 |
|
if (a->u.ptr->length == 0)
|
478 |
|
UNSET(a);
|
|
779 |
if (a->u.ptr->length == 0)
|
|
780 |
UNSET(a);
|
479 |
781 |
}
|
480 |
782 |
|
481 |
783 |
static void
|
482 |
784 |
bgp_decode_cluster_list(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
483 |
785 |
{
|
484 |
|
if (!s->proto->is_internal)
|
485 |
|
DISCARD(BAD_EBGP, "CLUSTER_LIST");
|
|
786 |
if (!s->proto->is_internal)
|
|
787 |
DISCARD(BAD_EBGP, "CLUSTER_LIST");
|
486 |
788 |
|
487 |
|
if (!len || (len % 4))
|
488 |
|
WITHDRAW(BAD_LENGTH, "CLUSTER_LIST", len);
|
|
789 |
if (!len || (len % 4))
|
|
790 |
WITHDRAW(BAD_LENGTH, "CLUSTER_LIST", len);
|
489 |
791 |
|
490 |
|
struct adata *ad = lp_alloc_adata(s->pool, len);
|
491 |
|
get_u32s(data, (u32 *) ad->data, len / 4);
|
492 |
|
bgp_set_attr_ptr(to, s->pool, BA_CLUSTER_LIST, flags, ad);
|
|
792 |
struct adata *ad = lp_alloc_adata(s->pool, len);
|
|
793 |
get_u32s(data, (u32 *) ad->data, len / 4);
|
|
794 |
bgp_set_attr_ptr(to, s->pool, BA_CLUSTER_LIST, flags, ad);
|
493 |
795 |
}
|
494 |
796 |
|
495 |
797 |
static void
|
496 |
798 |
bgp_format_cluster_list(eattr *a, byte *buf, uint size)
|
497 |
799 |
{
|
498 |
|
/* Truncates cluster lists larger than buflen, probably not a problem */
|
499 |
|
int_set_format(a->u.ptr, 0, -1, buf, size);
|
|
800 |
/* Truncates cluster lists larger than buflen, probably not a problem */
|
|
801 |
int_set_format(a->u.ptr, 0, -1, buf, size);
|
500 |
802 |
}
|
501 |
803 |
|
502 |
804 |
|
503 |
805 |
static inline u32
|
504 |
806 |
get_af3(byte *buf)
|
505 |
807 |
{
|
506 |
|
return (get_u16(buf) << 16) | buf[2];
|
|
808 |
return (get_u16(buf) << 16) | buf[2];
|
507 |
809 |
}
|
508 |
810 |
|
509 |
811 |
static void
|
510 |
812 |
bgp_decode_mp_reach_nlri(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUSED, byte *data, uint len, ea_list **to UNUSED)
|
511 |
813 |
{
|
512 |
|
/*
|
513 |
|
* 2 B MP_REACH_NLRI data - Address Family Identifier
|
514 |
|
* 1 B MP_REACH_NLRI data - Subsequent Address Family Identifier
|
515 |
|
* 1 B MP_REACH_NLRI data - Length of Next Hop Network Address
|
516 |
|
* var MP_REACH_NLRI data - Network Address of Next Hop
|
517 |
|
* 1 B MP_REACH_NLRI data - Reserved (zero)
|
518 |
|
* var MP_REACH_NLRI data - Network Layer Reachability Information
|
519 |
|
*/
|
|
814 |
/*
|
|
815 |
* 2 B MP_REACH_NLRI data - Address Family Identifier
|
|
816 |
* 1 B MP_REACH_NLRI data - Subsequent Address Family Identifier
|
|
817 |
* 1 B MP_REACH_NLRI data - Length of Next Hop Network Address
|
|
818 |
* var MP_REACH_NLRI data - Network Address of Next Hop
|
|
819 |
* 1 B MP_REACH_NLRI data - Reserved (zero)
|
|
820 |
* var MP_REACH_NLRI data - Network Layer Reachability Information
|
|
821 |
*/
|
520 |
822 |
|
521 |
|
if ((len < 5) || (len < (5 + (uint) data[3])))
|
|
823 |
if ((len < 5) || (len < (5 + (uint) data[3])))
|
522 |
824 |
bgp_parse_error(s, 9);
|
523 |
825 |
|
524 |
|
s->mp_reach_af = get_af3(data);
|
525 |
|
s->mp_next_hop_len = data[3];
|
526 |
|
s->mp_next_hop_data = data + 4;
|
527 |
|
s->mp_reach_len = len - 5 - s->mp_next_hop_len;
|
528 |
|
s->mp_reach_nlri = data + 5 + s->mp_next_hop_len;
|
|
826 |
s->mp_reach_af = get_af3(data);
|
|
827 |
s->mp_next_hop_len = data[3];
|
|
828 |
s->mp_next_hop_data = data + 4;
|
|
829 |
s->mp_reach_len = len - 5 - s->mp_next_hop_len;
|
|
830 |
s->mp_reach_nlri = data + 5 + s->mp_next_hop_len;
|
529 |
831 |
}
|
530 |
832 |
|
531 |
833 |
|
532 |
834 |
static void
|
533 |
835 |
bgp_decode_mp_unreach_nlri(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUSED, byte *data, uint len, ea_list **to UNUSED)
|
534 |
836 |
{
|
535 |
|
/*
|
536 |
|
* 2 B MP_UNREACH_NLRI data - Address Family Identifier
|
537 |
|
* 1 B MP_UNREACH_NLRI data - Subsequent Address Family Identifier
|
538 |
|
* var MP_UNREACH_NLRI data - Network Layer Reachability Information
|
539 |
|
*/
|
|
837 |
/*
|
|
838 |
* 2 B MP_UNREACH_NLRI data - Address Family Identifier
|
|
839 |
* 1 B MP_UNREACH_NLRI data - Subsequent Address Family Identifier
|
|
840 |
* var MP_UNREACH_NLRI data - Network Layer Reachability Information
|
|
841 |
*/
|
540 |
842 |
|
541 |
|
if (len < 3)
|
542 |
|
bgp_parse_error(s, 9);
|
|
843 |
if (len < 3)
|
|
844 |
bgp_parse_error(s, 9);
|
543 |
845 |
|
544 |
|
s->mp_unreach_af = get_af3(data);
|
545 |
|
s->mp_unreach_len = len - 3;
|
546 |
|
s->mp_unreach_nlri = data + 3;
|
|
846 |
s->mp_unreach_af = get_af3(data);
|
|
847 |
s->mp_unreach_len = len - 3;
|
|
848 |
s->mp_unreach_nlri = data + 3;
|
547 |
849 |
}
|
548 |
850 |
|
549 |
851 |
|
550 |
852 |
static void
|
551 |
853 |
bgp_export_ext_community(struct bgp_export_state *s, eattr *a)
|
552 |
854 |
{
|
553 |
|
a->u.ptr = ec_set_del_nontrans(s->pool, a->u.ptr);
|
|
855 |
a->u.ptr = ec_set_del_nontrans(s->pool, a->u.ptr);
|
554 |
856 |
|
555 |
|
if (a->u.ptr->length == 0)
|
556 |
|
UNSET(a);
|
|
857 |
if (a->u.ptr->length == 0)
|
|
858 |
UNSET(a);
|
557 |
859 |
|
558 |
|
ec_set_sort_x(a->u.ptr);
|
|
860 |
ec_set_sort_x(a->u.ptr);
|
559 |
861 |
}
|
560 |
862 |
|
561 |
863 |
static void
|
562 |
864 |
bgp_decode_ext_community(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
563 |
865 |
{
|
564 |
|
if (!len || (len % 8))
|
565 |
|
WITHDRAW(BAD_LENGTH, "EXT_COMMUNITY", len);
|
|
866 |
if (!len || (len % 8))
|
|
867 |
WITHDRAW(BAD_LENGTH, "EXT_COMMUNITY", len);
|
566 |
868 |
|
567 |
|
struct adata *ad = lp_alloc_adata(s->pool, len);
|
568 |
|
get_u32s(data, (u32 *) ad->data, len / 4);
|
569 |
|
bgp_set_attr_ptr(to, s->pool, BA_EXT_COMMUNITY, flags, ad);
|
|
869 |
struct adata *ad = lp_alloc_adata(s->pool, len);
|
|
870 |
get_u32s(data, (u32 *) ad->data, len / 4);
|
|
871 |
bgp_set_attr_ptr(to, s->pool, BA_EXT_COMMUNITY, flags, ad);
|
570 |
872 |
}
|
571 |
873 |
|
572 |
874 |
|
573 |
875 |
static void
|
574 |
876 |
bgp_decode_as4_aggregator(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
575 |
877 |
{
|
576 |
|
if (s->as4_session)
|
577 |
|
DISCARD(NEW_BGP, "AS4_AGGREGATOR");
|
|
878 |
if (s->as4_session)
|
|
879 |
DISCARD(NEW_BGP, "AS4_AGGREGATOR");
|
578 |
880 |
|
579 |
|
if (len != 8)
|
580 |
|
DISCARD(BAD_LENGTH, "AS4_AGGREGATOR", len);
|
|
881 |
if (len != 8)
|
|
882 |
DISCARD(BAD_LENGTH, "AS4_AGGREGATOR", len);
|
581 |
883 |
|
582 |
|
bgp_set_attr_data(to, s->pool, BA_AS4_AGGREGATOR, flags, data, len);
|
|
884 |
bgp_set_attr_data(to, s->pool, BA_AS4_AGGREGATOR, flags, data, len);
|
583 |
885 |
}
|
584 |
886 |
|
585 |
887 |
static void
|
586 |
888 |
bgp_decode_as4_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
587 |
889 |
{
|
588 |
|
char err[128];
|
|
890 |
char err[128];
|
589 |
891 |
|
590 |
|
if (s->as4_session)
|
591 |
|
DISCARD(NEW_BGP, "AS4_PATH");
|
|
892 |
if (s->as4_session)
|
|
893 |
DISCARD(NEW_BGP, "AS4_PATH");
|
592 |
894 |
|
593 |
|
if (len < 6)
|
594 |
|
DISCARD(BAD_LENGTH, "AS4_PATH", len);
|
|
895 |
if (len < 6)
|
|
896 |
DISCARD(BAD_LENGTH, "AS4_PATH", len);
|
595 |
897 |
|
596 |
|
if (!as_path_valid(data, len, 4, 1, err, sizeof(err)))
|
597 |
|
DISCARD("Malformed AS4_PATH attribute - %s", err);
|
|
898 |
if (!as_path_valid(data, len, 4, 1, err, sizeof(err)))
|
|
899 |
DISCARD("Malformed AS4_PATH attribute - %s", err);
|
598 |
900 |
|
599 |
|
struct adata *a = lp_alloc_adata(s->pool, len);
|
600 |
|
memcpy(a->data, data, len);
|
|
901 |
struct adata *a = lp_alloc_adata(s->pool, len);
|
|
902 |
memcpy(a->data, data, len);
|
601 |
903 |
|
602 |
|
/* AS_CONFED* segments are invalid in AS4_PATH; RFC 6793 6 */
|
603 |
|
if (as_path_contains_confed(a))
|
604 |
|
{
|
605 |
|
REPORT("Discarding AS_CONFED* segment from AS4_PATH attribute");
|
606 |
|
a = as_path_strip_confed(s->pool, a);
|
607 |
|
}
|
|
904 |
/* AS_CONFED* segments are invalid in AS4_PATH; RFC 6793 6 */
|
|
905 |
if (as_path_contains_confed(a))
|
|
906 |
{
|
|
907 |
REPORT("Discarding AS_CONFED* segment from AS4_PATH attribute");
|
|
908 |
a = as_path_strip_confed(s->pool, a);
|
|
909 |
}
|
608 |
910 |
|
609 |
|
bgp_set_attr_ptr(to, s->pool, BA_AS4_PATH, flags, a);
|
|
911 |
bgp_set_attr_ptr(to, s->pool, BA_AS4_PATH, flags, a);
|
610 |
912 |
}
|
611 |
913 |
|
612 |
914 |
static void
|
613 |
915 |
bgp_export_large_community(struct bgp_export_state *s, eattr *a)
|
614 |
916 |
{
|
615 |
|
if (a->u.ptr->length == 0)
|
616 |
|
UNSET(a);
|
|
917 |
if (a->u.ptr->length == 0)
|
|
918 |
UNSET(a);
|
617 |
919 |
|
618 |
|
a->u.ptr = lc_set_sort(s->pool, a->u.ptr);
|
|
920 |
a->u.ptr = lc_set_sort(s->pool, a->u.ptr);
|
619 |
921 |
}
|
620 |
922 |
|
621 |
923 |
static void
|
622 |
924 |
bgp_decode_large_community(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
|
623 |
925 |
{
|
624 |
|
if (!len || (len % 12))
|
625 |
|
WITHDRAW(BAD_LENGTH, "LARGE_COMMUNITY", len);
|
|
926 |
if (!len || (len % 12))
|
|
927 |
WITHDRAW(BAD_LENGTH, "LARGE_COMMUNITY", len);
|
626 |
928 |
|
627 |
|
struct adata *ad = lp_alloc_adata(s->pool, len);
|
628 |
|
get_u32s(data, (u32 *) ad->data, len / 4);
|
629 |
|
bgp_set_attr_ptr(to, s->pool, BA_LARGE_COMMUNITY, flags, ad);
|
|
929 |
struct adata *ad = lp_alloc_adata(s->pool, len);
|
|
930 |
get_u32s(data, (u32 *) ad->data, len / 4);
|
|
931 |
bgp_set_attr_ptr(to, s->pool, BA_LARGE_COMMUNITY, flags, ad);
|
630 |
932 |
}
|
631 |
933 |
|
632 |
934 |
static void
|
633 |
935 |
bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a)
|
634 |
936 |
{
|
635 |
|
net_addr *n = s->route->net->n.addr;
|
636 |
|
u32 *labels = (u32 *) a->u.ptr->data;
|
637 |
|
uint lnum = a->u.ptr->length / 4;
|
|
937 |
net_addr *n = s->route->net->n.addr;
|
|
938 |
u32 *labels = (u32 *) a->u.ptr->data;
|
|
939 |
uint lnum = a->u.ptr->length / 4;
|
638 |
940 |
|
639 |
|
/* Perhaps we should just ignore it? */
|
640 |
|
if (!s->mpls)
|
641 |
|
WITHDRAW("Unexpected MPLS stack");
|
|
941 |
/* Perhaps we should just ignore it? */
|
|
942 |
if (!s->mpls)
|
|
943 |
WITHDRAW("Unexpected MPLS stack");
|
642 |
944 |
|
643 |
|
/* Empty MPLS stack is not allowed */
|
644 |
|
if (!lnum)
|
645 |
|
WITHDRAW("Malformed MPLS stack - empty");
|
|
945 |
/* Empty MPLS stack is not allowed */
|
|
946 |
if (!lnum)
|
|
947 |
WITHDRAW("Malformed MPLS stack - empty");
|
646 |
948 |
|
647 |
|
/* This is ugly, but we must ensure that labels fit into NLRI field */
|
648 |
|
if ((24*lnum + (net_is_vpn(n) ? 64 : 0) + net_pxlen(n)) > 255)
|
649 |
|
WITHDRAW("Malformed MPLS stack - too many labels (%u)", lnum);
|
|
949 |
/* This is ugly, but we must ensure that labels fit into NLRI field */
|
|
950 |
if ((24*lnum + (net_is_vpn(n) ? 64 : 0) + net_pxlen(n)) > 255)
|
|
951 |
WITHDRAW("Malformed MPLS stack - too many labels (%u)", lnum);
|
650 |
952 |
|
651 |
|
for (uint i = 0; i < lnum; i++)
|
652 |
|
{
|
653 |
|
if (labels[i] > 0xfffff)
|
654 |
|
WITHDRAW("Malformed MPLS stack - invalid label (%u)", labels[i]);
|
655 |
|
|
656 |
|
/* TODO: Check for special-purpose label values? */
|
657 |
|
}
|
|
953 |
for (uint i = 0; i < lnum; i++)
|
|
954 |
{
|
|
955 |
if (labels[i] > 0xfffff)
|
|
956 |
WITHDRAW("Malformed MPLS stack - invalid label (%u)", labels[i]);
|
|
957 |
}
|
658 |
958 |
}
|
659 |
959 |
|
660 |
960 |
static int
|
661 |
961 |
bgp_encode_mpls_label_stack(struct bgp_write_state *s, eattr *a, byte *buf UNUSED, uint size UNUSED)
|
662 |
962 |
{
|
663 |
|
/*
|
664 |
|
* MPLS labels are encoded as a part of the NLRI in MP_REACH_NLRI attribute,
|
665 |
|
* so we store MPLS_LABEL_STACK and encode it later by AFI-specific hooks.
|
666 |
|
*/
|
|
963 |
/*
|
|
964 |
* MPLS labels are encoded as a part of the NLRI in MP_REACH_NLRI attribute,
|
|
965 |
* so we store MPLS_LABEL_STACK and encode it later by AFI-specific hooks.
|
|
966 |
*/
|
667 |
967 |
|
668 |
|
s->mpls_labels = a->u.ptr;
|
669 |
|
return 0;
|
|
968 |
s->mpls_labels = a->u.ptr;
|
|
969 |
return 0;
|
670 |
970 |
}
|
671 |
971 |
|
672 |
972 |
static void
|
673 |
973 |
bgp_decode_mpls_label_stack(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUSED, byte *data UNUSED, uint len UNUSED, ea_list **to UNUSED)
|
674 |
974 |
{
|
675 |
|
DISCARD("Discarding received attribute #0");
|
|
975 |
DISCARD("Discarding received attribute #0");
|
676 |
976 |
}
|
677 |
977 |
|
678 |
978 |
static void
|
679 |
979 |
bgp_format_mpls_label_stack(eattr *a, byte *buf, uint size)
|
680 |
980 |
{
|
681 |
|
u32 *labels = (u32 *) a->u.ptr->data;
|
682 |
|
uint lnum = a->u.ptr->length / 4;
|
683 |
|
char *pos = buf;
|
|
981 |
u32 *labels = (u32 *) a->u.ptr->data;
|
|
982 |
uint lnum = a->u.ptr->length / 4;
|
|
983 |
char *pos = buf;
|
684 |
984 |
|
685 |
|
for (uint i = 0; i < lnum; i++)
|
686 |
|
{
|
687 |
|
if (size < 20)
|
|
985 |
for (uint i = 0; i < lnum; i++)
|
688 |
986 |
{
|
689 |
|
bsprintf(pos, "...");
|
690 |
|
return;
|
|
987 |
if (size < 20)
|
|
988 |
{
|
|
989 |
bsprintf(pos, "...");
|
|
990 |
return;
|
|
991 |
}
|
|
992 |
|
|
993 |
uint l = bsprintf(pos, "%d/", labels[i]);
|
|
994 |
ADVANCE(pos, size, l);
|
691 |
995 |
}
|
692 |
996 |
|
693 |
|
uint l = bsprintf(pos, "%d/", labels[i]);
|
694 |
|
ADVANCE(pos, size, l);
|
695 |
|
}
|
696 |
|
|
697 |
|
/* Clear last slash or terminate empty string */
|
698 |
|
pos[lnum ? -1 : 0] = 0;
|
|
997 |
/* Clear last slash or terminate empty string */
|
|
998 |
pos[lnum ? -1 : 0] = 0;
|
699 |
999 |
}
|
700 |
1000 |
|
701 |
1001 |
static inline void
|
702 |
1002 |
bgp_decode_unknown(struct bgp_parse_state *s, uint code, uint flags, byte *data, uint len, ea_list **to)
|
703 |
1003 |
{
|
704 |
|
/* Cannot use bgp_set_attr_data() as it works on known attributes only */
|
705 |
|
ea_set_attr_data(to, s->pool, EA_CODE(EAP_BGP, code), flags, EAF_TYPE_OPAQUE, data, len);
|
|
1004 |
/* Cannot use bgp_set_attr_data() as it works on known attributes only */
|
|
1005 |
ea_set_attr_data(to, s->pool, EA_CODE(EAP_BGP, code), flags, EAF_TYPE_OPAQUE, data, len);
|
706 |
1006 |
}
|
707 |
1007 |
|
708 |
1008 |
|
... | ... | |
711 |
1011 |
*/
|
712 |
1012 |
|
713 |
1013 |
static const struct bgp_attr_desc bgp_attr_table[] = {
|
714 |
|
[BA_ORIGIN] = {
|
715 |
|
.name = "origin",
|
716 |
|
.type = EAF_TYPE_INT,
|
717 |
|
.flags = BAF_TRANSITIVE,
|
718 |
|
.export = bgp_export_origin,
|
719 |
|
.encode = bgp_encode_u8,
|
720 |
|
.decode = bgp_decode_origin,
|
721 |
|
.format = bgp_format_origin,
|
722 |
|
},
|
723 |
|
[BA_AS_PATH] = {
|
724 |
|
.name = "as_path",
|
725 |
|
.type = EAF_TYPE_AS_PATH,
|
726 |
|
.flags = BAF_TRANSITIVE,
|
727 |
|
.encode = bgp_encode_as_path,
|
728 |
|
.decode = bgp_decode_as_path,
|
729 |
|
},
|
730 |
|
[BA_NEXT_HOP] = {
|
731 |
|
.name = "next_hop",
|
732 |
|
.type = EAF_TYPE_IP_ADDRESS,
|
733 |
|
.flags = BAF_TRANSITIVE,
|
734 |
|
.encode = bgp_encode_next_hop,
|
735 |
|
.decode = bgp_decode_next_hop,
|
736 |
|
.format = bgp_format_next_hop,
|
737 |
|
},
|
738 |
|
[BA_MULTI_EXIT_DISC] = {
|
739 |
|
.name = "med",
|
740 |
|
.type = EAF_TYPE_INT,
|
741 |
|
.flags = BAF_OPTIONAL,
|
742 |
|
.encode = bgp_encode_u32,
|
743 |
|
.decode = bgp_decode_med,
|
744 |
|
},
|
745 |
|
[BA_LOCAL_PREF] = {
|
746 |
|
.name = "local_pref",
|
747 |
|
.type = EAF_TYPE_INT,
|
748 |
|
.flags = BAF_TRANSITIVE,
|
749 |
|
.export = bgp_export_local_pref,
|
750 |
|
.encode = bgp_encode_u32,
|
751 |
|
.decode = bgp_decode_local_pref,
|
752 |
|
},
|
753 |
|
[BA_ATOMIC_AGGR] = {
|
754 |
|
.name = "atomic_aggr",
|
755 |
|
.type = EAF_TYPE_OPAQUE,
|
756 |
|
.flags = BAF_TRANSITIVE,
|
757 |
|
.encode = bgp_encode_raw,
|
758 |
|
.decode = bgp_decode_atomic_aggr,
|
759 |
|
},
|
760 |
|
[BA_AGGREGATOR] = {
|
761 |
|
.name = "aggregator",
|
762 |
|
.type = EAF_TYPE_OPAQUE,
|
763 |
|
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
764 |
|
.encode = bgp_encode_aggregator,
|
765 |
|
.decode = bgp_decode_aggregator,
|
766 |
|
.format = bgp_format_aggregator,
|
767 |
|
},
|
768 |
|
[BA_COMMUNITY] = {
|
769 |
|
.name = "community",
|
770 |
|
.type = EAF_TYPE_INT_SET,
|
771 |
|
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
772 |
|
.export = bgp_export_community,
|
773 |
|
.encode = bgp_encode_u32s,
|
774 |
|
.decode = bgp_decode_community,
|
775 |
|
},
|
776 |
|
[BA_ORIGINATOR_ID] = {
|
777 |
|
.name = "originator_id",
|
778 |
|
.type = EAF_TYPE_ROUTER_ID,
|
779 |
|
.flags = BAF_OPTIONAL,
|
780 |
|
.export = bgp_export_originator_id,
|
781 |
|
.encode = bgp_encode_u32,
|
782 |
|
.decode = bgp_decode_originator_id,
|
783 |
|
},
|
784 |
|
[BA_CLUSTER_LIST] = {
|
785 |
|
.name = "cluster_list",
|
786 |
|
.type = EAF_TYPE_INT_SET,
|
787 |
|
.flags = BAF_OPTIONAL,
|
788 |
|
.export = bgp_export_cluster_list,
|
789 |
|
.encode = bgp_encode_u32s,
|
790 |
|
.decode = bgp_decode_cluster_list,
|
791 |
|
.format = bgp_format_cluster_list,
|
792 |
|
},
|
793 |
|
[BA_MP_REACH_NLRI] = {
|
794 |
|
.name = "mp_reach_nlri",
|
795 |
|
.type = EAF_TYPE_OPAQUE,
|
796 |
|
.flags = BAF_OPTIONAL,
|
797 |
|
.decode = bgp_decode_mp_reach_nlri,
|
798 |
|
},
|
799 |
|
[BA_MP_UNREACH_NLRI] = {
|
800 |
|
.name = "mp_unreach_nlri",
|
801 |
|
.type = EAF_TYPE_OPAQUE,
|
802 |
|
.flags = BAF_OPTIONAL,
|
803 |
|
.decode = bgp_decode_mp_unreach_nlri,
|
804 |
|
},
|
805 |
|
[BA_EXT_COMMUNITY] = {
|
806 |
|
.name = "ext_community",
|
807 |
|
.type = EAF_TYPE_EC_SET,
|
808 |
|
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
809 |
|
.export = bgp_export_ext_community,
|
810 |
|
.encode = bgp_encode_u32s,
|
811 |
|
.decode = bgp_decode_ext_community,
|
812 |
|
},
|
813 |
|
[BA_AS4_PATH] = {
|
814 |
|
.name = "as4_path",
|
815 |
|
.type = EAF_TYPE_AS_PATH,
|
816 |
|
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
817 |
|
.encode = bgp_encode_raw,
|
818 |
|
.decode = bgp_decode_as4_path,
|
819 |
|
},
|
820 |
|
[BA_AS4_AGGREGATOR] = {
|
821 |
|
.name = "as4_aggregator",
|
822 |
|
.type = EAF_TYPE_OPAQUE,
|
823 |
|
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
824 |
|
.encode = bgp_encode_raw,
|
825 |
|
.decode = bgp_decode_as4_aggregator,
|
826 |
|
.format = bgp_format_aggregator,
|
827 |
|
},
|
828 |
|
[BA_LARGE_COMMUNITY] = {
|
829 |
|
.name = "large_community",
|
830 |
|
.type = EAF_TYPE_LC_SET,
|
831 |
|
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
832 |
|
.export = bgp_export_large_community,
|
833 |
|
.encode = bgp_encode_u32s,
|
834 |
|
.decode = bgp_decode_large_community,
|
835 |
|
},
|
836 |
|
[BA_MPLS_LABEL_STACK] = {
|
837 |
|
.name = "mpls_label_stack",
|
838 |
|
.type = EAF_TYPE_INT_SET,
|
839 |
|
.export = bgp_export_mpls_label_stack,
|
840 |
|
.encode = bgp_encode_mpls_label_stack,
|
841 |
|
.decode = bgp_decode_mpls_label_stack,
|
842 |
|
.format = bgp_format_mpls_label_stack,
|
843 |
|
},
|
|
1014 |
[BA_ORIGIN] = {
|
|
1015 |
.name = "origin",
|
|
1016 |
.type = EAF_TYPE_INT,
|
|
1017 |
.flags = BAF_TRANSITIVE,
|
|
1018 |
.export = bgp_export_origin,
|
|
1019 |
.encode = bgp_encode_u8,
|
|
1020 |
.decode = bgp_decode_origin,
|
|
1021 |
.format = bgp_format_origin,
|
|
1022 |
},
|
|
1023 |
[BA_AS_PATH] = {
|
|
1024 |
.name = "as_path",
|
|
1025 |
.type = EAF_TYPE_AS_PATH,
|
|
1026 |
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
|
1027 |
.encode = bgp_encode_as_path,
|
|
1028 |
.decode = bgp_decode_as_path,
|
|
1029 |
},
|
|
1030 |
[BA_AS_NH_LIST] = {
|
|
1031 |
.name = "NH",
|
|
1032 |
.type = EAF_TYPE_AS_PATH,
|
|
1033 |
.flags = BAF_TRANSITIVE, //-> documentation
|
|
1034 |
.encode = bgp_encode_nhs_list,
|
|
1035 |
.decode = bgp_decode_nhs_list,
|
|
1036 |
},
|
|
1037 |
[BA_AS_LOAD] = {
|
|
1038 |
.name = "AS_LOAD",
|
|
1039 |
.type = EAF_TYPE_AS_PATH,
|
|
1040 |
.flags = BAF_TRANSITIVE,
|
|
1041 |
.encode = bgp_encode_as_load,
|
|
1042 |
.decode = bgp_decode_as_load,
|
|
1043 |
},
|
|
1044 |
[BA_LOAD_OUT] = {
|
|
1045 |
.name = "load_out",
|
|
1046 |
.type = EAF_TYPE_INT,
|
|
1047 |
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
|
1048 |
.encode = bgp_encode_u32,
|
|
1049 |
.decode = bgp_decode_load_out,
|
|
1050 |
},
|
|
1051 |
[BA_NEXT_HOP] = {
|
|
1052 |
.name = "next_hop",
|
|
1053 |
.type = EAF_TYPE_IP_ADDRESS,
|
|
1054 |
.flags = BAF_TRANSITIVE,
|
|
1055 |
.encode = bgp_encode_next_hop,
|
|
1056 |
.decode = bgp_decode_next_hop,
|
|
1057 |
.format = bgp_format_next_hop,
|
|
1058 |
},
|
|
1059 |
[BA_MULTI_EXIT_DISC] = {
|
|
1060 |
.name = "med",
|
|
1061 |
.type = EAF_TYPE_INT,
|
|
1062 |
.flags = BAF_OPTIONAL,
|
|
1063 |
.encode = bgp_encode_u32,
|
|
1064 |
.decode = bgp_decode_med,
|
|
1065 |
},
|
|
1066 |
[BA_LOCAL_PREF] = {
|
|
1067 |
.name = "local_pref",
|
|
1068 |
.type = EAF_TYPE_INT,
|
|
1069 |
.flags = BAF_TRANSITIVE,
|
|
1070 |
.export = bgp_export_local_pref,
|
|
1071 |
.encode = bgp_encode_u32,
|
|
1072 |
.decode = bgp_decode_local_pref,
|
|
1073 |
},
|
|
1074 |
[BA_ATOMIC_AGGR] = {
|
|
1075 |
.name = "atomic_aggr",
|
|
1076 |
.type = EAF_TYPE_OPAQUE,
|
|
1077 |
.flags = BAF_TRANSITIVE,
|
|
1078 |
.encode = bgp_encode_raw,
|
|
1079 |
.decode = bgp_decode_atomic_aggr,
|
|
1080 |
},
|
|
1081 |
[BA_AGGREGATOR] = {
|
|
1082 |
.name = "aggregator",
|
|
1083 |
.type = EAF_TYPE_OPAQUE,
|
|
1084 |
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
|
1085 |
.encode = bgp_encode_aggregator,
|
|
1086 |
.decode = bgp_decode_aggregator,
|
|
1087 |
.format = bgp_format_aggregator,
|
|
1088 |
},
|
|
1089 |
[BA_COMMUNITY] = {
|
|
1090 |
.name = "community",
|
|
1091 |
.type = EAF_TYPE_INT_SET,
|
|
1092 |
.flags = BAF_OPTIONAL | BAF_TRANSITIVE,
|
|
1093 |
.export = bgp_export_community,
|
|
1094 |
.encode = bgp_encode_u32s,
|
|
1095 |
.decode = bgp_decode_community,
|
|
1096 |
},
|
|
1097 |
[BA_ORIGINATOR_ID] = {
|
|
1098 |
.name = "originator_id",
|
|
1099 |
.type = EAF_TYPE_ROUTER_ID,
|
|
1100 |
.flags = BAF_OPTIONAL,
|
|
1101 |
.export = bgp_export_originator_id,
|
|
1102 |
.encode = bgp_encode_u32,
|
|
1103 |
.decode = bgp_decode_originator_id,
|
|
1104 |
},
|
|
1105 |
[BA_CLUSTER_LIST] = {
|
|
1106 |
.name = "cluster_list",
|
|
1107 |
.type = EAF_TYPE_INT_SET,
|
|
1108 |
.flags = BAF_OPTIONAL,
|
|
1109 |
.export = bgp_export_cluster_list,
|
|
1110 |
.encode = bgp_encode_u32s,
|
|
1111 |
.decode = bgp_decode_cluster_list,
|
|
1112 |
.format = bgp_format_cluster_list,
|
|
1113 |
},
|
|
1114 |
[BA_MP_REACH_NLRI] = {
|
|
1115 |
.name = "mp_reach_nlri",
|
|
1116 |
.type = EAF_TYPE_OPAQUE,
|
|
1117 |
.flags = BAF_OPTIONAL,
|
|
1118 |
.decode = bgp_decode_mp_reach_nlri,
|
|
1119 |
},
|
|
1120 |
[BA_MP_UNREACH_NLRI] = {
|