Revision ef5081af

View differences:

proto/bgp/Makefile
1
src := attrs.c bgp.c packets.c
1
src := attrs.c bgp.c packets.c map.c
2 2
obj := $(src-o-files)
3 3
$(all-daemon)
4 4
$(cf-local)
5 5

  
6
tests_objs := $(tests_objs) $(src-o-files)
6
tests_objs := $(tests_objs) $(src-o-files)
proto/bgp/attrs.c
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] = {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff