Coverage Report

Created: 2025-12-12 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_attr.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* BGP attributes management routines.
3
 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4
 */
5
6
#include <zebra.h>
7
8
#include "linklist.h"
9
#include "prefix.h"
10
#include "memory.h"
11
#include "vector.h"
12
#include "stream.h"
13
#include "log.h"
14
#include "hash.h"
15
#include "jhash.h"
16
#include "queue.h"
17
#include "table.h"
18
#include "filter.h"
19
#include "command.h"
20
#include "srv6.h"
21
#include "frrstr.h"
22
23
#include "bgpd/bgpd.h"
24
#include "bgpd/bgp_attr.h"
25
#include "bgpd/bgp_route.h"
26
#include "bgpd/bgp_aspath.h"
27
#include "bgpd/bgp_community.h"
28
#include "bgpd/bgp_debug.h"
29
#include "bgpd/bgp_errors.h"
30
#include "bgpd/bgp_label.h"
31
#include "bgpd/bgp_packet.h"
32
#include "bgpd/bgp_ecommunity.h"
33
#include "bgpd/bgp_lcommunity.h"
34
#include "bgpd/bgp_updgrp.h"
35
#include "bgpd/bgp_encap_types.h"
36
#ifdef ENABLE_BGP_VNC
37
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
38
#include "bgp_encap_types.h"
39
#include "bgp_vnc_types.h"
40
#endif
41
#include "bgp_evpn.h"
42
#include "bgp_flowspec_private.h"
43
#include "bgp_mac.h"
44
45
/* Attribute strings for logging. */
46
static const struct message attr_str[] = {
47
  {BGP_ATTR_ORIGIN, "ORIGIN"},
48
  {BGP_ATTR_AS_PATH, "AS_PATH"},
49
  {BGP_ATTR_NEXT_HOP, "NEXT_HOP"},
50
  {BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC"},
51
  {BGP_ATTR_LOCAL_PREF, "LOCAL_PREF"},
52
  {BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE"},
53
  {BGP_ATTR_AGGREGATOR, "AGGREGATOR"},
54
  {BGP_ATTR_COMMUNITIES, "COMMUNITY"},
55
  {BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID"},
56
  {BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST"},
57
  {BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI"},
58
  {BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI"},
59
  {BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES"},
60
  {BGP_ATTR_AS4_PATH, "AS4_PATH"},
61
  {BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"},
62
  {BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
63
  {BGP_ATTR_ENCAP, "ENCAP"},
64
  {BGP_ATTR_OTC, "OTC"},
65
#ifdef ENABLE_BGP_VNC_ATTR
66
  {BGP_ATTR_VNC, "VNC"},
67
#endif
68
  {BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
69
  {BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
70
  {BGP_ATTR_IPV6_EXT_COMMUNITIES, "IPV6_EXT_COMMUNITIES"},
71
  {BGP_ATTR_AIGP, "AIGP"},
72
  {0}};
73
74
static const struct message attr_flag_str[] = {
75
  {BGP_ATTR_FLAG_OPTIONAL, "Optional"},
76
  {BGP_ATTR_FLAG_TRANS, "Transitive"},
77
  {BGP_ATTR_FLAG_PARTIAL, "Partial"},
78
  /* bgp_attr_flags_diagnose() relies on this bit being last in
79
     this list */
80
  {BGP_ATTR_FLAG_EXTLEN, "Extended Length"},
81
  {0}};
82
83
static struct hash *cluster_hash;
84
85
static void *cluster_hash_alloc(void *p)
86
20
{
87
20
  const struct cluster_list *val = (const struct cluster_list *)p;
88
20
  struct cluster_list *cluster;
89
90
20
  cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list));
91
20
  cluster->length = val->length;
92
93
20
  if (cluster->length) {
94
20
    cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length);
95
20
    memcpy(cluster->list, val->list, val->length);
96
20
  } else
97
0
    cluster->list = NULL;
98
99
20
  cluster->refcnt = 0;
100
101
20
  return cluster;
102
20
}
103
104
/* Cluster list related functions. */
105
static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
106
20
{
107
20
  struct cluster_list tmp = {};
108
20
  struct cluster_list *cluster;
109
110
20
  tmp.length = length;
111
20
  tmp.list = length == 0 ? NULL : pnt;
112
113
20
  cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc);
114
20
  cluster->refcnt++;
115
20
  return cluster;
116
20
}
117
118
bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
119
1
{
120
1
  int i;
121
122
5
  for (i = 0; i < cluster->length / 4; i++)
123
4
    if (cluster->list[i].s_addr == originator.s_addr)
124
0
      return true;
125
1
  return false;
126
1
}
127
128
static unsigned int cluster_hash_key_make(const void *p)
129
40
{
130
40
  const struct cluster_list *cluster = p;
131
132
40
  return jhash(cluster->list, cluster->length, 0);
133
40
}
134
135
static bool cluster_hash_cmp(const void *p1, const void *p2)
136
20
{
137
20
  const struct cluster_list *cluster1 = p1;
138
20
  const struct cluster_list *cluster2 = p2;
139
140
20
  if (cluster1->list == cluster2->list)
141
20
    return true;
142
143
0
  if (!cluster1->list || !cluster2->list)
144
0
    return false;
145
146
0
  if (cluster1->length != cluster2->length)
147
0
    return false;
148
149
0
  return (memcmp(cluster1->list, cluster2->list, cluster1->length) == 0);
150
0
}
151
152
static void cluster_free(struct cluster_list *cluster)
153
20
{
154
20
  XFREE(MTYPE_CLUSTER_VAL, cluster->list);
155
20
  XFREE(MTYPE_CLUSTER, cluster);
156
20
}
157
158
static struct cluster_list *cluster_intern(struct cluster_list *cluster)
159
0
{
160
0
  struct cluster_list *find;
161
162
0
  find = hash_get(cluster_hash, cluster, cluster_hash_alloc);
163
0
  find->refcnt++;
164
165
0
  return find;
166
0
}
167
168
static void cluster_unintern(struct cluster_list **cluster)
169
20
{
170
20
  if ((*cluster)->refcnt)
171
20
    (*cluster)->refcnt--;
172
173
20
  if ((*cluster)->refcnt == 0) {
174
20
    void *p = hash_release(cluster_hash, *cluster);
175
20
    assert(p == *cluster);
176
20
    cluster_free(*cluster);
177
20
    *cluster = NULL;
178
20
  }
179
20
}
180
181
static void cluster_init(void)
182
1
{
183
1
  cluster_hash = hash_create(cluster_hash_key_make, cluster_hash_cmp,
184
1
           "BGP Cluster");
185
1
}
186
187
static void cluster_finish(void)
188
0
{
189
0
  hash_clean_and_free(&cluster_hash, (void (*)(void *))cluster_free);
190
0
}
191
192
static struct hash *encap_hash = NULL;
193
#ifdef ENABLE_BGP_VNC
194
static struct hash *vnc_hash = NULL;
195
#endif
196
static struct hash *srv6_l3vpn_hash;
197
static struct hash *srv6_vpn_hash;
198
199
struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig)
200
0
{
201
0
  struct bgp_attr_encap_subtlv *new;
202
0
  struct bgp_attr_encap_subtlv *tail;
203
0
  struct bgp_attr_encap_subtlv *p;
204
205
0
  for (p = orig, tail = new = NULL; p; p = p->next) {
206
0
    int size = sizeof(struct bgp_attr_encap_subtlv) + p->length;
207
0
    if (tail) {
208
0
      tail->next = XCALLOC(MTYPE_ENCAP_TLV, size);
209
0
      tail = tail->next;
210
0
    } else {
211
0
      tail = new = XCALLOC(MTYPE_ENCAP_TLV, size);
212
0
    }
213
0
    assert(tail);
214
0
    memcpy(tail, p, size);
215
0
    tail->next = NULL;
216
0
  }
217
218
0
  return new;
219
0
}
220
221
static void encap_free(struct bgp_attr_encap_subtlv *p)
222
6
{
223
6
  struct bgp_attr_encap_subtlv *next;
224
542
  while (p) {
225
536
    next = p->next;
226
536
    p->next = NULL;
227
536
    XFREE(MTYPE_ENCAP_TLV, p);
228
536
    p = next;
229
536
  }
230
6
}
231
232
void bgp_attr_flush_encap(struct attr *attr)
233
178
{
234
178
  if (!attr)
235
0
    return;
236
237
178
  if (attr->encap_subtlvs) {
238
1
    encap_free(attr->encap_subtlvs);
239
1
    attr->encap_subtlvs = NULL;
240
1
  }
241
178
#ifdef ENABLE_BGP_VNC
242
178
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
243
178
    bgp_attr_get_vnc_subtlvs(attr);
244
245
178
  if (vnc_subtlvs) {
246
0
    encap_free(vnc_subtlvs);
247
0
    bgp_attr_set_vnc_subtlvs(attr, NULL);
248
0
  }
249
178
#endif
250
178
}
251
252
/*
253
 * Compare encap sub-tlv chains
254
 *
255
 *  1 = equivalent
256
 *  0 = not equivalent
257
 *
258
 * This algorithm could be made faster if needed
259
 */
260
static bool encap_same(const struct bgp_attr_encap_subtlv *h1,
261
           const struct bgp_attr_encap_subtlv *h2)
262
5
{
263
5
  const struct bgp_attr_encap_subtlv *p;
264
5
  const struct bgp_attr_encap_subtlv *q;
265
266
5
  if (h1 == h2)
267
5
    return true;
268
0
  if (h1 == NULL || h2 == NULL)
269
0
    return false;
270
271
0
  for (p = h1; p; p = p->next) {
272
0
    for (q = h2; q; q = q->next) {
273
0
      if ((p->type == q->type) && (p->length == q->length)
274
0
          && !memcmp(p->value, q->value, p->length)) {
275
276
0
        break;
277
0
      }
278
0
    }
279
0
    if (!q)
280
0
      return false;
281
0
  }
282
283
0
  for (p = h2; p; p = p->next) {
284
0
    for (q = h1; q; q = q->next) {
285
0
      if ((p->type == q->type) && (p->length == q->length)
286
0
          && !memcmp(p->value, q->value, p->length)) {
287
288
0
        break;
289
0
      }
290
0
    }
291
0
    if (!q)
292
0
      return false;
293
0
  }
294
295
0
  return true;
296
0
}
297
298
static void *encap_hash_alloc(void *p)
299
5
{
300
  /* Encap structure is already allocated.  */
301
5
  return p;
302
5
}
303
304
typedef enum {
305
  ENCAP_SUBTLV_TYPE,
306
#ifdef ENABLE_BGP_VNC
307
  VNC_SUBTLV_TYPE
308
#endif
309
} encap_subtlv_type;
310
311
static struct bgp_attr_encap_subtlv *
312
encap_intern(struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
313
5
{
314
5
  struct bgp_attr_encap_subtlv *find;
315
5
  struct hash *hash = encap_hash;
316
5
#ifdef ENABLE_BGP_VNC
317
5
  if (type == VNC_SUBTLV_TYPE)
318
0
    hash = vnc_hash;
319
5
#endif
320
321
5
  find = hash_get(hash, encap, encap_hash_alloc);
322
5
  if (find != encap)
323
0
    encap_free(encap);
324
5
  find->refcnt++;
325
326
5
  return find;
327
5
}
328
329
static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
330
         encap_subtlv_type type)
331
5
{
332
5
  struct bgp_attr_encap_subtlv *encap = *encapp;
333
5
  if (encap->refcnt)
334
5
    encap->refcnt--;
335
336
5
  if (encap->refcnt == 0) {
337
5
    struct hash *hash = encap_hash;
338
5
#ifdef ENABLE_BGP_VNC
339
5
    if (type == VNC_SUBTLV_TYPE)
340
0
      hash = vnc_hash;
341
5
#endif
342
5
    hash_release(hash, encap);
343
5
    encap_free(encap);
344
5
    *encapp = NULL;
345
5
  }
346
5
}
347
348
static unsigned int encap_hash_key_make(const void *p)
349
10
{
350
10
  const struct bgp_attr_encap_subtlv *encap = p;
351
352
10
  return jhash(encap->value, encap->length, 0);
353
10
}
354
355
static bool encap_hash_cmp(const void *p1, const void *p2)
356
5
{
357
5
  return encap_same((const struct bgp_attr_encap_subtlv *)p1,
358
5
        (const struct bgp_attr_encap_subtlv *)p2);
359
5
}
360
361
static void encap_init(void)
362
1
{
363
1
  encap_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
364
1
         "BGP Encap Hash");
365
1
#ifdef ENABLE_BGP_VNC
366
1
  vnc_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
367
1
             "BGP VNC Hash");
368
1
#endif
369
1
}
370
371
static void encap_finish(void)
372
0
{
373
0
  hash_clean_and_free(&encap_hash, (void (*)(void *))encap_free);
374
0
#ifdef ENABLE_BGP_VNC
375
0
  hash_clean_and_free(&vnc_hash, (void (*)(void *))encap_free);
376
0
#endif
377
0
}
378
379
static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
380
0
{
381
0
  if (!a1 && a2)
382
0
    return false;
383
0
  if (!a2 && a1)
384
0
    return false;
385
0
  if (!a1 && !a2)
386
0
    return true;
387
388
0
  return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1),
389
0
           bgp_attr_get_evpn_overlay(a2));
390
0
}
391
392
/* Unknown transit attribute. */
393
static struct hash *transit_hash;
394
395
static void transit_free(struct transit *transit)
396
141
{
397
141
  XFREE(MTYPE_TRANSIT_VAL, transit->val);
398
141
  XFREE(MTYPE_TRANSIT, transit);
399
141
}
400
401
static void *transit_hash_alloc(void *p)
402
128
{
403
  /* Transit structure is already allocated.  */
404
128
  return p;
405
128
}
406
407
static struct transit *transit_intern(struct transit *transit)
408
128
{
409
128
  struct transit *find;
410
411
128
  find = hash_get(transit_hash, transit, transit_hash_alloc);
412
128
  if (find != transit)
413
0
    transit_free(transit);
414
128
  find->refcnt++;
415
416
128
  return find;
417
128
}
418
419
static void transit_unintern(struct transit **transit)
420
128
{
421
128
  if ((*transit)->refcnt)
422
128
    (*transit)->refcnt--;
423
424
128
  if ((*transit)->refcnt == 0) {
425
128
    hash_release(transit_hash, *transit);
426
128
    transit_free(*transit);
427
128
    *transit = NULL;
428
128
  }
429
128
}
430
431
static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length,
432
           uint64_t *aigp)
433
0
{
434
0
  uint8_t *data = pnt;
435
0
  uint8_t tlv_type;
436
0
  uint16_t tlv_length;
437
438
0
  while (length) {
439
0
    tlv_type = *data;
440
0
    ptr_get_be16(data + 1, &tlv_length);
441
0
    (void)data;
442
443
    /* The value field of the AIGP TLV is always 8 octets
444
     * long and its value is interpreted as an unsigned 64-bit
445
     * integer.
446
     */
447
0
    if (tlv_type == BGP_AIGP_TLV_METRIC) {
448
0
      (void)ptr_get_be64(data + 3, aigp);
449
450
      /* If an AIGP attribute is received and its first AIGP
451
       * TLV contains the maximum value 0xffffffffffffffff,
452
       * the attribute SHOULD be considered to be malformed
453
       * and SHOULD be discarded as specified in this section.
454
       */
455
0
      if (*aigp == BGP_AIGP_TLV_METRIC_MAX) {
456
0
        zlog_err("Bad AIGP TLV (%s) length: %llu",
457
0
           BGP_AIGP_TLV_METRIC_DESC,
458
0
           BGP_AIGP_TLV_METRIC_MAX);
459
0
        return false;
460
0
      }
461
462
0
      return true;
463
0
    }
464
465
0
    data += tlv_length;
466
0
    length -= tlv_length;
467
0
  }
468
469
0
  return false;
470
0
}
471
472
static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
473
0
{
474
0
  uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
475
476
0
  if (bpi->nexthop)
477
0
    return aigp + bpi->nexthop->metric;
478
0
  else
479
0
    return aigp;
480
0
}
481
482
static void stream_put_bgp_aigp_tlv_metric(struct stream *s,
483
             struct bgp_path_info *bpi)
484
0
{
485
0
  stream_putc(s, BGP_AIGP_TLV_METRIC);
486
0
  stream_putw(s, BGP_AIGP_TLV_METRIC_LEN);
487
0
  stream_putq(s, bgp_aigp_metric_total(bpi));
488
0
}
489
490
static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
491
0
{
492
0
  uint8_t *data = pnt;
493
0
  uint8_t tlv_type;
494
0
  uint16_t tlv_length;
495
0
  uint8_t *end = data + length;
496
497
0
  if (length < 3) {
498
0
    zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
499
0
       length);
500
0
    return false;
501
0
  }
502
503
0
  while (length) {
504
0
    size_t data_len = end - data;
505
506
0
    tlv_type = *data;
507
508
0
    if (data_len - 1 < 2)
509
0
      return false;
510
511
0
    ptr_get_be16(data + 1, &tlv_length);
512
0
    (void)data;
513
514
0
    if (length < tlv_length) {
515
0
      zlog_err(
516
0
        "Bad AIGP attribute length: %u, but TLV length: %u",
517
0
        length, tlv_length);
518
0
      return false;
519
0
    }
520
521
0
    if (tlv_length < 3) {
522
0
      zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
523
0
         tlv_length);
524
0
      return false;
525
0
    }
526
527
    /* AIGP TLV, Length: 11 */
528
0
    if (tlv_type == BGP_AIGP_TLV_METRIC &&
529
0
        tlv_length != BGP_AIGP_TLV_METRIC_LEN) {
530
0
      zlog_err("Bad AIGP TLV (%s) length: %u",
531
0
         BGP_AIGP_TLV_METRIC_DESC, tlv_length);
532
0
      return false;
533
0
    }
534
535
0
    data += tlv_length;
536
0
    length -= tlv_length;
537
0
  }
538
539
0
  return true;
540
0
}
541
542
static void *srv6_l3vpn_hash_alloc(void *p)
543
6
{
544
6
  return p;
545
6
}
546
547
static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn *l3vpn)
548
9
{
549
9
  XFREE(MTYPE_BGP_SRV6_L3VPN, l3vpn);
550
9
}
551
552
static struct bgp_attr_srv6_l3vpn *
553
srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn *l3vpn)
554
6
{
555
6
  struct bgp_attr_srv6_l3vpn *find;
556
557
6
  find = hash_get(srv6_l3vpn_hash, l3vpn, srv6_l3vpn_hash_alloc);
558
6
  if (find != l3vpn)
559
0
    srv6_l3vpn_free(l3vpn);
560
6
  find->refcnt++;
561
6
  return find;
562
6
}
563
564
static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn **l3vpnp)
565
9
{
566
9
  struct bgp_attr_srv6_l3vpn *l3vpn = *l3vpnp;
567
568
9
  if (l3vpn->refcnt)
569
6
    l3vpn->refcnt--;
570
571
9
  if (l3vpn->refcnt == 0) {
572
9
    hash_release(srv6_l3vpn_hash, l3vpn);
573
9
    srv6_l3vpn_free(l3vpn);
574
9
    *l3vpnp = NULL;
575
9
  }
576
9
}
577
578
static void *srv6_vpn_hash_alloc(void *p)
579
0
{
580
0
  return p;
581
0
}
582
583
static void srv6_vpn_free(struct bgp_attr_srv6_vpn *vpn)
584
0
{
585
0
  XFREE(MTYPE_BGP_SRV6_VPN, vpn);
586
0
}
587
588
static struct bgp_attr_srv6_vpn *srv6_vpn_intern(struct bgp_attr_srv6_vpn *vpn)
589
0
{
590
0
  struct bgp_attr_srv6_vpn *find;
591
592
0
  find = hash_get(srv6_vpn_hash, vpn, srv6_vpn_hash_alloc);
593
0
  if (find != vpn)
594
0
    srv6_vpn_free(vpn);
595
0
  find->refcnt++;
596
0
  return find;
597
0
}
598
599
static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn **vpnp)
600
0
{
601
0
  struct bgp_attr_srv6_vpn *vpn = *vpnp;
602
603
0
  if (vpn->refcnt)
604
0
    vpn->refcnt--;
605
606
0
  if (vpn->refcnt == 0) {
607
0
    hash_release(srv6_vpn_hash, vpn);
608
0
    srv6_vpn_free(vpn);
609
0
    *vpnp = NULL;
610
0
  }
611
0
}
612
613
static uint32_t srv6_l3vpn_hash_key_make(const void *p)
614
15
{
615
15
  const struct bgp_attr_srv6_l3vpn *l3vpn = p;
616
15
  uint32_t key = 0;
617
618
15
  key = jhash(&l3vpn->sid, 16, key);
619
15
  key = jhash_1word(l3vpn->sid_flags, key);
620
15
  key = jhash_1word(l3vpn->endpoint_behavior, key);
621
15
  key = jhash_1word(l3vpn->loc_block_len, key);
622
15
  key = jhash_1word(l3vpn->loc_node_len, key);
623
15
  key = jhash_1word(l3vpn->func_len, key);
624
15
  key = jhash_1word(l3vpn->arg_len, key);
625
15
  key = jhash_1word(l3vpn->transposition_len, key);
626
15
  key = jhash_1word(l3vpn->transposition_offset, key);
627
15
  return key;
628
15
}
629
630
static bool srv6_l3vpn_hash_cmp(const void *p1, const void *p2)
631
6
{
632
6
  const struct bgp_attr_srv6_l3vpn *l3vpn1 = p1;
633
6
  const struct bgp_attr_srv6_l3vpn *l3vpn2 = p2;
634
635
6
  return sid_same(&l3vpn1->sid, &l3vpn2->sid)
636
6
         && l3vpn1->sid_flags == l3vpn2->sid_flags
637
6
         && l3vpn1->endpoint_behavior == l3vpn2->endpoint_behavior
638
6
         && l3vpn1->loc_block_len == l3vpn2->loc_block_len
639
6
         && l3vpn1->loc_node_len == l3vpn2->loc_node_len
640
6
         && l3vpn1->func_len == l3vpn2->func_len
641
6
         && l3vpn1->arg_len == l3vpn2->arg_len
642
6
         && l3vpn1->transposition_len == l3vpn2->transposition_len
643
6
         && l3vpn1->transposition_offset == l3vpn2->transposition_offset;
644
6
}
645
646
static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn *h1,
647
          const struct bgp_attr_srv6_l3vpn *h2)
648
0
{
649
0
  if (h1 == h2)
650
0
    return true;
651
0
  else if (h1 == NULL || h2 == NULL)
652
0
    return false;
653
0
  else
654
0
    return srv6_l3vpn_hash_cmp((const void *)h1, (const void *)h2);
655
0
}
656
657
static unsigned int srv6_vpn_hash_key_make(const void *p)
658
0
{
659
0
  const struct bgp_attr_srv6_vpn *vpn = p;
660
0
  uint32_t key = 0;
661
662
0
  key = jhash(&vpn->sid, 16, key);
663
0
  key = jhash_1word(vpn->sid_flags, key);
664
0
  return key;
665
0
}
666
667
static bool srv6_vpn_hash_cmp(const void *p1, const void *p2)
668
0
{
669
0
  const struct bgp_attr_srv6_vpn *vpn1 = p1;
670
0
  const struct bgp_attr_srv6_vpn *vpn2 = p2;
671
672
0
  return sid_same(&vpn1->sid, &vpn2->sid)
673
0
         && vpn1->sid_flags == vpn2->sid_flags;
674
0
}
675
676
static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn *h1,
677
        const struct bgp_attr_srv6_vpn *h2)
678
0
{
679
0
  if (h1 == h2)
680
0
    return true;
681
0
  else if (h1 == NULL || h2 == NULL)
682
0
    return false;
683
0
  else
684
0
    return srv6_vpn_hash_cmp((const void *)h1, (const void *)h2);
685
0
}
686
687
static void srv6_init(void)
688
1
{
689
1
  srv6_l3vpn_hash =
690
1
    hash_create(srv6_l3vpn_hash_key_make, srv6_l3vpn_hash_cmp,
691
1
          "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
692
1
  srv6_vpn_hash = hash_create(srv6_vpn_hash_key_make, srv6_vpn_hash_cmp,
693
1
            "BGP Prefix-SID SRv6-VPN-Service-TLV");
694
1
}
695
696
static void srv6_finish(void)
697
0
{
698
0
  hash_clean_and_free(&srv6_l3vpn_hash,
699
0
          (void (*)(void *))srv6_l3vpn_free);
700
0
  hash_clean_and_free(&srv6_vpn_hash, (void (*)(void *))srv6_vpn_free);
701
0
}
702
703
static unsigned int transit_hash_key_make(const void *p)
704
256
{
705
256
  const struct transit *transit = p;
706
707
256
  return jhash(transit->val, transit->length, 0);
708
256
}
709
710
static bool transit_hash_cmp(const void *p1, const void *p2)
711
128
{
712
128
  const struct transit *transit1 = p1;
713
128
  const struct transit *transit2 = p2;
714
715
128
  return (transit1->length == transit2->length
716
128
    && memcmp(transit1->val, transit2->val, transit1->length) == 0);
717
128
}
718
719
static void transit_init(void)
720
1
{
721
1
  transit_hash = hash_create(transit_hash_key_make, transit_hash_cmp,
722
1
           "BGP Transit Hash");
723
1
}
724
725
static void transit_finish(void)
726
0
{
727
0
  hash_clean_and_free(&transit_hash, (void (*)(void *))transit_free);
728
0
}
729
730
/* Attribute hash routines. */
731
static struct hash *attrhash;
732
733
unsigned long int attr_count(void)
734
0
{
735
0
  return attrhash->count;
736
0
}
737
738
unsigned long int attr_unknown_count(void)
739
0
{
740
0
  return transit_hash->count;
741
0
}
742
743
unsigned int attrhash_key_make(const void *p)
744
0
{
745
0
  const struct attr *attr = (struct attr *)p;
746
0
  uint32_t key = 0;
747
0
#define MIX(val)  key = jhash_1word(val, key)
748
0
#define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key)
749
750
0
  MIX3(attr->origin, attr->nexthop.s_addr, attr->med);
751
0
  MIX3(attr->local_pref, attr->aggregator_as,
752
0
       attr->aggregator_addr.s_addr);
753
0
  MIX3(attr->weight, attr->mp_nexthop_global_in.s_addr,
754
0
       attr->originator_id.s_addr);
755
0
  MIX3(attr->tag, attr->label, attr->label_index);
756
757
0
  if (attr->aspath)
758
0
    MIX(aspath_key_make(attr->aspath));
759
0
  if (bgp_attr_get_community(attr))
760
0
    MIX(community_hash_make(bgp_attr_get_community(attr)));
761
0
  if (bgp_attr_get_lcommunity(attr))
762
0
    MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr)));
763
0
  if (bgp_attr_get_ecommunity(attr))
764
0
    MIX(ecommunity_hash_make(bgp_attr_get_ecommunity(attr)));
765
0
  if (bgp_attr_get_ipv6_ecommunity(attr))
766
0
    MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr)));
767
0
  if (bgp_attr_get_cluster(attr))
768
0
    MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr)));
769
0
  if (bgp_attr_get_transit(attr))
770
0
    MIX(transit_hash_key_make(bgp_attr_get_transit(attr)));
771
0
  if (attr->encap_subtlvs)
772
0
    MIX(encap_hash_key_make(attr->encap_subtlvs));
773
0
  if (attr->srv6_l3vpn)
774
0
    MIX(srv6_l3vpn_hash_key_make(attr->srv6_l3vpn));
775
0
  if (attr->srv6_vpn)
776
0
    MIX(srv6_vpn_hash_key_make(attr->srv6_vpn));
777
0
#ifdef ENABLE_BGP_VNC
778
0
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
779
0
    bgp_attr_get_vnc_subtlvs(attr);
780
0
  if (vnc_subtlvs)
781
0
    MIX(encap_hash_key_make(vnc_subtlvs));
782
0
#endif
783
0
  MIX(attr->mp_nexthop_len);
784
0
  key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
785
0
  key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
786
0
  MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance);
787
0
  MIX(attr->rmap_table_id);
788
0
  MIX(attr->nh_type);
789
0
  MIX(attr->bh_type);
790
0
  MIX(attr->otc);
791
0
  MIX(bgp_attr_get_aigp_metric(attr));
792
793
0
  return key;
794
0
}
795
796
bool attrhash_cmp(const void *p1, const void *p2)
797
0
{
798
0
  const struct attr *attr1 = p1;
799
0
  const struct attr *attr2 = p2;
800
801
0
  if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
802
0
      && attr1->nexthop.s_addr == attr2->nexthop.s_addr
803
0
      && attr1->aspath == attr2->aspath
804
0
      && bgp_attr_get_community(attr1)
805
0
        == bgp_attr_get_community(attr2)
806
0
    && attr1->med == attr2->med
807
0
      && attr1->local_pref == attr2->local_pref
808
0
      && attr1->rmap_change_flags == attr2->rmap_change_flags) {
809
0
    if (attr1->aggregator_as == attr2->aggregator_as &&
810
0
        attr1->aggregator_addr.s_addr ==
811
0
          attr2->aggregator_addr.s_addr &&
812
0
        attr1->weight == attr2->weight &&
813
0
        attr1->tag == attr2->tag &&
814
0
        attr1->label_index == attr2->label_index &&
815
0
        attr1->mp_nexthop_len == attr2->mp_nexthop_len &&
816
0
        bgp_attr_get_ecommunity(attr1) ==
817
0
          bgp_attr_get_ecommunity(attr2) &&
818
0
        bgp_attr_get_ipv6_ecommunity(attr1) ==
819
0
          bgp_attr_get_ipv6_ecommunity(attr2) &&
820
0
        bgp_attr_get_lcommunity(attr1) ==
821
0
          bgp_attr_get_lcommunity(attr2) &&
822
0
        bgp_attr_get_cluster(attr1) ==
823
0
          bgp_attr_get_cluster(attr2) &&
824
0
        bgp_attr_get_transit(attr1) ==
825
0
          bgp_attr_get_transit(attr2) &&
826
0
        bgp_attr_get_aigp_metric(attr1) ==
827
0
          bgp_attr_get_aigp_metric(attr2) &&
828
0
        attr1->rmap_table_id == attr2->rmap_table_id &&
829
0
        (attr1->encap_tunneltype == attr2->encap_tunneltype) &&
830
0
        encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
831
0
#ifdef ENABLE_BGP_VNC
832
0
        && encap_same(bgp_attr_get_vnc_subtlvs(attr1),
833
0
          bgp_attr_get_vnc_subtlvs(attr2))
834
0
#endif
835
0
        && IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
836
0
              &attr2->mp_nexthop_global) &&
837
0
        IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
838
0
           &attr2->mp_nexthop_local) &&
839
0
        IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
840
0
           &attr2->mp_nexthop_global_in) &&
841
0
        IPV4_ADDR_SAME(&attr1->originator_id,
842
0
           &attr2->originator_id) &&
843
0
        overlay_index_same(attr1, attr2) &&
844
0
        !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) &&
845
0
        attr1->es_flags == attr2->es_flags &&
846
0
        attr1->mm_sync_seqnum == attr2->mm_sync_seqnum &&
847
0
        attr1->df_pref == attr2->df_pref &&
848
0
        attr1->df_alg == attr2->df_alg &&
849
0
        attr1->nh_ifindex == attr2->nh_ifindex &&
850
0
        attr1->nh_lla_ifindex == attr2->nh_lla_ifindex &&
851
0
        attr1->distance == attr2->distance &&
852
0
        srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn) &&
853
0
        srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
854
0
        attr1->srte_color == attr2->srte_color &&
855
0
        attr1->nh_type == attr2->nh_type &&
856
0
        attr1->bh_type == attr2->bh_type &&
857
0
        attr1->otc == attr2->otc)
858
0
      return true;
859
0
  }
860
861
0
  return false;
862
0
}
863
864
static void attrhash_init(void)
865
1
{
866
1
  attrhash =
867
1
    hash_create(attrhash_key_make, attrhash_cmp, "BGP Attributes");
868
1
}
869
870
/*
871
 * special for hash_clean below
872
 */
873
static void attr_vfree(void *attr)
874
0
{
875
0
  XFREE(MTYPE_ATTR, attr);
876
0
}
877
878
static void attrhash_finish(void)
879
0
{
880
0
  hash_clean_and_free(&attrhash, attr_vfree);
881
0
}
882
883
static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
884
0
{
885
0
  struct attr *attr = bucket->data;
886
0
  struct in6_addr *sid = NULL;
887
888
0
  if (attr->srv6_l3vpn)
889
0
    sid = &attr->srv6_l3vpn->sid;
890
0
  else if (attr->srv6_vpn)
891
0
    sid = &attr->srv6_vpn->sid;
892
893
0
  vty_out(vty, "attr[%ld] nexthop %pI4\n", attr->refcnt, &attr->nexthop);
894
895
0
  vty_out(vty,
896
0
    "\tflags: %" PRIu64
897
0
    " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
898
0
    attr->flag, attr->distance, attr->med, attr->local_pref,
899
0
    attr->origin, attr->weight, attr->label, sid);
900
0
}
901
902
void attr_show_all(struct vty *vty)
903
0
{
904
0
  hash_iterate(attrhash, (void (*)(struct hash_bucket *,
905
0
           void *))attr_show_all_iterator,
906
0
         vty);
907
0
}
908
909
static void *bgp_attr_hash_alloc(void *p)
910
0
{
911
0
  struct attr *val = (struct attr *)p;
912
0
  struct attr *attr;
913
914
0
  attr = XMALLOC(MTYPE_ATTR, sizeof(struct attr));
915
0
  *attr = *val;
916
0
  if (val->encap_subtlvs) {
917
0
    val->encap_subtlvs = NULL;
918
0
  }
919
0
#ifdef ENABLE_BGP_VNC
920
0
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
921
0
    bgp_attr_get_vnc_subtlvs(val);
922
923
0
  if (vnc_subtlvs)
924
0
    bgp_attr_set_vnc_subtlvs(val, NULL);
925
0
#endif
926
927
0
  attr->refcnt = 0;
928
0
  return attr;
929
0
}
930
931
/* Internet argument attribute. */
932
struct attr *bgp_attr_intern(struct attr *attr)
933
0
{
934
0
  struct attr *find;
935
0
  struct ecommunity *ecomm = NULL;
936
0
  struct ecommunity *ipv6_ecomm = NULL;
937
0
  struct lcommunity *lcomm = NULL;
938
0
  struct community *comm = NULL;
939
940
  /* Intern referenced structure. */
941
0
  if (attr->aspath) {
942
0
    if (!attr->aspath->refcnt)
943
0
      attr->aspath = aspath_intern(attr->aspath);
944
0
    else
945
0
      attr->aspath->refcnt++;
946
0
  }
947
948
0
  comm = bgp_attr_get_community(attr);
949
0
  if (comm) {
950
0
    if (!comm->refcnt)
951
0
      bgp_attr_set_community(attr, community_intern(comm));
952
0
    else
953
0
      comm->refcnt++;
954
0
  }
955
956
0
  ecomm = bgp_attr_get_ecommunity(attr);
957
0
  if (ecomm) {
958
0
    if (!ecomm->refcnt)
959
0
      bgp_attr_set_ecommunity(attr, ecommunity_intern(ecomm));
960
0
    else
961
0
      ecomm->refcnt++;
962
0
  }
963
964
0
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
965
0
  if (ipv6_ecomm) {
966
0
    if (!ipv6_ecomm->refcnt)
967
0
      bgp_attr_set_ipv6_ecommunity(
968
0
        attr, ecommunity_intern(ipv6_ecomm));
969
0
    else
970
0
      ipv6_ecomm->refcnt++;
971
0
  }
972
973
0
  lcomm = bgp_attr_get_lcommunity(attr);
974
0
  if (lcomm) {
975
0
    if (!lcomm->refcnt)
976
0
      bgp_attr_set_lcommunity(attr, lcommunity_intern(lcomm));
977
0
    else
978
0
      lcomm->refcnt++;
979
0
  }
980
981
0
  struct cluster_list *cluster = bgp_attr_get_cluster(attr);
982
983
0
  if (cluster) {
984
0
    if (!cluster->refcnt)
985
0
      bgp_attr_set_cluster(attr, cluster_intern(cluster));
986
0
    else
987
0
      cluster->refcnt++;
988
0
  }
989
990
0
  struct transit *transit = bgp_attr_get_transit(attr);
991
992
0
  if (transit) {
993
0
    if (!transit->refcnt)
994
0
      bgp_attr_set_transit(attr, transit_intern(transit));
995
0
    else
996
0
      transit->refcnt++;
997
0
  }
998
0
  if (attr->encap_subtlvs) {
999
0
    if (!attr->encap_subtlvs->refcnt)
1000
0
      attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
1001
0
                 ENCAP_SUBTLV_TYPE);
1002
0
    else
1003
0
      attr->encap_subtlvs->refcnt++;
1004
0
  }
1005
0
  if (attr->srv6_l3vpn) {
1006
0
    if (!attr->srv6_l3vpn->refcnt)
1007
0
      attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
1008
0
    else
1009
0
      attr->srv6_l3vpn->refcnt++;
1010
0
  }
1011
0
  if (attr->srv6_vpn) {
1012
0
    if (!attr->srv6_vpn->refcnt)
1013
0
      attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
1014
0
    else
1015
0
      attr->srv6_vpn->refcnt++;
1016
0
  }
1017
0
#ifdef ENABLE_BGP_VNC
1018
0
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1019
0
    bgp_attr_get_vnc_subtlvs(attr);
1020
1021
0
  if (vnc_subtlvs) {
1022
0
    if (!vnc_subtlvs->refcnt)
1023
0
      bgp_attr_set_vnc_subtlvs(
1024
0
        attr,
1025
0
        encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
1026
0
    else
1027
0
      vnc_subtlvs->refcnt++;
1028
0
  }
1029
0
#endif
1030
1031
  /* At this point, attr only contains intern'd pointers.  that means
1032
   * if we find it in attrhash, it has all the same pointers and we
1033
   * correctly updated the refcounts on these.
1034
   * If we don't find it, we need to allocate a one because in all
1035
   * cases this returns a new reference to a hashed attr, but the input
1036
   * wasn't on hash. */
1037
0
  find = (struct attr *)hash_get(attrhash, attr, bgp_attr_hash_alloc);
1038
0
  find->refcnt++;
1039
1040
0
  return find;
1041
0
}
1042
1043
/* Make network statement's attribute. */
1044
struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
1045
          uint8_t origin)
1046
0
{
1047
0
  memset(attr, 0, sizeof(struct attr));
1048
1049
0
  attr->origin = origin;
1050
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1051
0
  attr->aspath = aspath_empty(bgp->asnotation);
1052
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1053
0
  attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
1054
0
  attr->tag = 0;
1055
0
  attr->label_index = BGP_INVALID_LABEL_INDEX;
1056
0
  attr->label = MPLS_INVALID_LABEL;
1057
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1058
0
  attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
1059
0
  attr->local_pref = bgp->default_local_pref;
1060
1061
0
  return attr;
1062
0
}
1063
1064
/* Create the attributes for an aggregate */
1065
struct attr *bgp_attr_aggregate_intern(
1066
  struct bgp *bgp, uint8_t origin, struct aspath *aspath,
1067
  struct community *community, struct ecommunity *ecommunity,
1068
  struct lcommunity *lcommunity, struct bgp_aggregate *aggregate,
1069
  uint8_t atomic_aggregate, const struct prefix *p)
1070
0
{
1071
0
  struct attr attr;
1072
0
  struct attr *new;
1073
0
  route_map_result_t ret;
1074
1075
0
  memset(&attr, 0, sizeof(attr));
1076
1077
  /* Origin attribute. */
1078
0
  attr.origin = origin;
1079
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1080
1081
  /* MED */
1082
0
  attr.med = 0;
1083
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1084
1085
  /* AS path attribute. */
1086
0
  if (aspath)
1087
0
    attr.aspath = aspath_intern(aspath);
1088
0
  else
1089
0
    attr.aspath = aspath_empty(bgp->asnotation);
1090
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1091
1092
0
  if (community) {
1093
0
    uint32_t gshut = COMMUNITY_GSHUT;
1094
1095
    /* If we are not shutting down ourselves and we are
1096
     * aggregating a route that contains the GSHUT community we
1097
     * need to remove that community when creating the aggregate */
1098
0
    if (!bgp_in_graceful_shutdown(bgp)
1099
0
        && community_include(community, gshut)) {
1100
0
      community_del_val(community, &gshut);
1101
0
    }
1102
1103
0
    bgp_attr_set_community(&attr, community);
1104
0
  }
1105
1106
0
  if (ecommunity)
1107
0
    bgp_attr_set_ecommunity(&attr, ecommunity);
1108
1109
0
  if (lcommunity)
1110
0
    bgp_attr_set_lcommunity(&attr, lcommunity);
1111
1112
0
  if (bgp_in_graceful_shutdown(bgp))
1113
0
    bgp_attr_add_gshut_community(&attr);
1114
1115
0
  attr.label_index = BGP_INVALID_LABEL_INDEX;
1116
0
  attr.label = MPLS_INVALID_LABEL;
1117
0
  attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
1118
0
  attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
1119
0
  if (!aggregate->as_set || atomic_aggregate)
1120
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1121
0
  attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
1122
0
  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
1123
0
    attr.aggregator_as = bgp->confed_id;
1124
0
  else
1125
0
    attr.aggregator_as = bgp->as;
1126
0
  attr.aggregator_addr = bgp->router_id;
1127
1128
  /* Aggregate are done for IPv4/IPv6 so checking ipv4 family,
1129
   * This should only be set for IPv4 AFI type
1130
   * based on RFC-4760:
1131
   * "An UPDATE message that carries no NLRI,
1132
   * other than the one encoded in
1133
   * the MP_REACH_NLRI attribute,
1134
   * SHOULD NOT carry the NEXT_HOP
1135
   * attribute"
1136
   */
1137
0
  if (p->family == AF_INET) {
1138
    /* Next hop attribute.  */
1139
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1140
0
    attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
1141
0
  }
1142
1143
  /* Apply route-map */
1144
0
  if (aggregate->rmap.name) {
1145
0
    struct attr attr_tmp = attr;
1146
0
    struct bgp_path_info rmap_path;
1147
1148
0
    memset(&rmap_path, 0, sizeof(rmap_path));
1149
0
    rmap_path.peer = bgp->peer_self;
1150
0
    rmap_path.attr = &attr_tmp;
1151
1152
0
    SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1153
1154
0
    ret = route_map_apply(aggregate->rmap.map, p, &rmap_path);
1155
1156
0
    bgp->peer_self->rmap_type = 0;
1157
1158
0
    if (ret == RMAP_DENYMATCH) {
1159
      /* Free uninterned attribute. */
1160
0
      bgp_attr_flush(&attr_tmp);
1161
1162
      /* Unintern original. */
1163
0
      aspath_unintern(&attr.aspath);
1164
0
      return NULL;
1165
0
    }
1166
1167
0
    if (bgp_in_graceful_shutdown(bgp))
1168
0
      bgp_attr_add_gshut_community(&attr_tmp);
1169
1170
0
    new = bgp_attr_intern(&attr_tmp);
1171
0
  } else {
1172
1173
0
    if (bgp_in_graceful_shutdown(bgp))
1174
0
      bgp_attr_add_gshut_community(&attr);
1175
1176
0
    new = bgp_attr_intern(&attr);
1177
0
  }
1178
1179
  /* Always release the 'intern()'ed AS Path. */
1180
0
  aspath_unintern(&attr.aspath);
1181
1182
0
  return new;
1183
0
}
1184
1185
/* Unintern just the sub-components of the attr, but not the attr */
1186
void bgp_attr_unintern_sub(struct attr *attr)
1187
610
{
1188
610
  struct ecommunity *ecomm = NULL;
1189
610
  struct ecommunity *ipv6_ecomm = NULL;
1190
610
  struct cluster_list *cluster;
1191
610
  struct lcommunity *lcomm = NULL;
1192
610
  struct community *comm = NULL;
1193
1194
  /* aspath refcount shoud be decrement. */
1195
610
  aspath_unintern(&attr->aspath);
1196
610
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
1197
1198
610
  comm = bgp_attr_get_community(attr);
1199
610
  community_unintern(&comm);
1200
610
  bgp_attr_set_community(attr, NULL);
1201
1202
610
  ecomm = bgp_attr_get_ecommunity(attr);
1203
610
  ecommunity_unintern(&ecomm);
1204
610
  bgp_attr_set_ecommunity(attr, NULL);
1205
1206
610
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1207
610
  ecommunity_unintern(&ipv6_ecomm);
1208
610
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1209
1210
610
  lcomm = bgp_attr_get_lcommunity(attr);
1211
610
  lcommunity_unintern(&lcomm);
1212
610
  bgp_attr_set_lcommunity(attr, NULL);
1213
1214
610
  cluster = bgp_attr_get_cluster(attr);
1215
610
  if (cluster) {
1216
20
    cluster_unintern(&cluster);
1217
20
    bgp_attr_set_cluster(attr, cluster);
1218
20
  }
1219
610
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
1220
1221
610
  struct transit *transit = bgp_attr_get_transit(attr);
1222
1223
610
  if (transit) {
1224
128
    transit_unintern(&transit);
1225
128
    bgp_attr_set_transit(attr, transit);
1226
128
  }
1227
1228
610
  if (attr->encap_subtlvs)
1229
5
    encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
1230
1231
610
#ifdef ENABLE_BGP_VNC
1232
610
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1233
610
    bgp_attr_get_vnc_subtlvs(attr);
1234
1235
610
  if (vnc_subtlvs) {
1236
0
    encap_unintern(&vnc_subtlvs, VNC_SUBTLV_TYPE);
1237
0
    bgp_attr_set_vnc_subtlvs(attr, vnc_subtlvs);
1238
0
  }
1239
610
#endif
1240
1241
610
  if (attr->srv6_l3vpn)
1242
9
    srv6_l3vpn_unintern(&attr->srv6_l3vpn);
1243
1244
610
  if (attr->srv6_vpn)
1245
0
    srv6_vpn_unintern(&attr->srv6_vpn);
1246
610
}
1247
1248
/* Free bgp attribute and aspath. */
1249
void bgp_attr_unintern(struct attr **pattr)
1250
0
{
1251
0
  struct attr *attr = *pattr;
1252
0
  struct attr *ret;
1253
0
  struct attr tmp;
1254
1255
  /* Decrement attribute reference. */
1256
0
  attr->refcnt--;
1257
1258
0
  tmp = *attr;
1259
1260
  /* If reference becomes zero then free attribute object. */
1261
0
  if (attr->refcnt == 0) {
1262
0
    ret = hash_release(attrhash, attr);
1263
0
    assert(ret != NULL);
1264
0
    XFREE(MTYPE_ATTR, attr);
1265
0
    *pattr = NULL;
1266
0
  }
1267
1268
0
  bgp_attr_unintern_sub(&tmp);
1269
0
}
1270
1271
void bgp_attr_flush(struct attr *attr)
1272
2.07k
{
1273
2.07k
  struct ecommunity *ecomm;
1274
2.07k
  struct ecommunity *ipv6_ecomm;
1275
2.07k
  struct cluster_list *cluster;
1276
2.07k
  struct lcommunity *lcomm;
1277
2.07k
  struct community *comm;
1278
1279
2.07k
  if (attr->aspath && !attr->aspath->refcnt) {
1280
0
    aspath_free(attr->aspath);
1281
0
    attr->aspath = NULL;
1282
0
  }
1283
2.07k
  comm = bgp_attr_get_community(attr);
1284
2.07k
  if (comm && !comm->refcnt)
1285
287
    community_free(&comm);
1286
2.07k
  bgp_attr_set_community(attr, NULL);
1287
1288
2.07k
  ecomm = bgp_attr_get_ecommunity(attr);
1289
2.07k
  if (ecomm && !ecomm->refcnt)
1290
0
    ecommunity_free(&ecomm);
1291
2.07k
  bgp_attr_set_ecommunity(attr, NULL);
1292
1293
2.07k
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1294
2.07k
  if (ipv6_ecomm && !ipv6_ecomm->refcnt)
1295
0
    ecommunity_free(&ipv6_ecomm);
1296
2.07k
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1297
1298
2.07k
  lcomm = bgp_attr_get_lcommunity(attr);
1299
2.07k
  if (lcomm && !lcomm->refcnt)
1300
0
    lcommunity_free(&lcomm);
1301
2.07k
  bgp_attr_set_lcommunity(attr, NULL);
1302
1303
2.07k
  cluster = bgp_attr_get_cluster(attr);
1304
2.07k
  if (cluster && !cluster->refcnt) {
1305
0
    cluster_free(cluster);
1306
0
    bgp_attr_set_cluster(attr, NULL);
1307
0
  }
1308
1309
2.07k
  struct transit *transit = bgp_attr_get_transit(attr);
1310
1311
2.07k
  if (transit && !transit->refcnt) {
1312
0
    transit_free(transit);
1313
0
    bgp_attr_set_transit(attr, NULL);
1314
0
  }
1315
2.07k
  if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) {
1316
0
    encap_free(attr->encap_subtlvs);
1317
0
    attr->encap_subtlvs = NULL;
1318
0
  }
1319
2.07k
  if (attr->srv6_l3vpn && !attr->srv6_l3vpn->refcnt) {
1320
0
    srv6_l3vpn_free(attr->srv6_l3vpn);
1321
0
    attr->srv6_l3vpn = NULL;
1322
0
  }
1323
2.07k
  if (attr->srv6_vpn && !attr->srv6_vpn->refcnt) {
1324
0
    srv6_vpn_free(attr->srv6_vpn);
1325
0
    attr->srv6_vpn = NULL;
1326
0
  }
1327
2.07k
#ifdef ENABLE_BGP_VNC
1328
2.07k
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1329
2.07k
    bgp_attr_get_vnc_subtlvs(attr);
1330
1331
2.07k
  if (vnc_subtlvs && !vnc_subtlvs->refcnt) {
1332
0
    encap_free(vnc_subtlvs);
1333
0
    bgp_attr_set_vnc_subtlvs(attr, NULL);
1334
0
  }
1335
2.07k
#endif
1336
2.07k
}
1337
1338
/* Implement draft-scudder-idr-optional-transitive behaviour and
1339
 * avoid resetting sessions for malformed attributes which are
1340
 * are partial/optional and hence where the error likely was not
1341
 * introduced by the sending neighbour.
1342
 */
1343
static enum bgp_attr_parse_ret
1344
bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
1345
       bgp_size_t length)
1346
155
{
1347
155
  struct peer *const peer = args->peer;
1348
155
  struct attr *const attr = args->attr;
1349
155
  const uint8_t flags = args->flags;
1350
  /* startp and length must be special-cased, as whether or not to
1351
   * send the attribute data with the NOTIFY depends on the error,
1352
   * the caller therefore signals this with the seperate length argument
1353
   */
1354
155
  uint8_t *notify_datap = (length > 0 ? args->startp : NULL);
1355
1356
155
  if (bgp_debug_update(peer, NULL, NULL, 1)) {
1357
0
    char attr_str[BUFSIZ] = {0};
1358
1359
0
    bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1360
1361
0
    zlog_debug("%s: attributes: %s", __func__, attr_str);
1362
0
  }
1363
1364
  /* Only relax error handling for eBGP peers */
1365
155
  if (peer->sort != BGP_PEER_EBGP) {
1366
0
    bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1367
0
            notify_datap, length);
1368
0
    return BGP_ATTR_PARSE_ERROR;
1369
0
  }
1370
1371
  /* Adjust the stream getp to the end of the attribute, in case we can
1372
   * still proceed but the caller hasn't read all the attribute.
1373
   */
1374
155
  stream_set_getp(BGP_INPUT(peer),
1375
155
      (args->startp - STREAM_DATA(BGP_INPUT(peer)))
1376
155
        + args->total);
1377
1378
155
  switch (args->type) {
1379
  /* where an attribute is relatively inconsequential, e.g. it does not
1380
   * affect route selection, and can be safely ignored, then any such
1381
   * attributes which are malformed should just be ignored and the route
1382
   * processed as normal.
1383
   */
1384
2
  case BGP_ATTR_AS4_AGGREGATOR:
1385
7
  case BGP_ATTR_AGGREGATOR:
1386
20
  case BGP_ATTR_ATOMIC_AGGREGATE:
1387
20
    return BGP_ATTR_PARSE_PROCEED;
1388
1389
  /* Core attributes, particularly ones which may influence route
1390
   * selection, should be treat-as-withdraw.
1391
   */
1392
12
  case BGP_ATTR_ORIGIN:
1393
22
  case BGP_ATTR_AS_PATH:
1394
38
  case BGP_ATTR_AS4_PATH:
1395
41
  case BGP_ATTR_NEXT_HOP:
1396
47
  case BGP_ATTR_MULTI_EXIT_DISC:
1397
47
  case BGP_ATTR_LOCAL_PREF:
1398
47
  case BGP_ATTR_COMMUNITIES:
1399
48
  case BGP_ATTR_EXT_COMMUNITIES:
1400
51
  case BGP_ATTR_IPV6_EXT_COMMUNITIES:
1401
56
  case BGP_ATTR_LARGE_COMMUNITIES:
1402
57
  case BGP_ATTR_ORIGINATOR_ID:
1403
57
  case BGP_ATTR_CLUSTER_LIST:
1404
58
  case BGP_ATTR_PMSI_TUNNEL:
1405
63
  case BGP_ATTR_ENCAP:
1406
63
  case BGP_ATTR_OTC:
1407
63
    return BGP_ATTR_PARSE_WITHDRAW;
1408
0
  case BGP_ATTR_MP_REACH_NLRI:
1409
0
  case BGP_ATTR_MP_UNREACH_NLRI:
1410
0
    bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode,
1411
0
            notify_datap, length);
1412
0
    return BGP_ATTR_PARSE_ERROR;
1413
155
  }
1414
1415
  /* Partial optional attributes that are malformed should not cause
1416
   * the whole session to be reset. Instead treat it as a withdrawal
1417
   * of the routes, if possible.
1418
   */
1419
72
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
1420
37
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1421
33
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
1422
13
    return BGP_ATTR_PARSE_WITHDRAW;
1423
1424
  /* default to reset */
1425
59
  return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1426
72
}
1427
1428
/* Find out what is wrong with the path attribute flag bits and log the error.
1429
   "Flag bits" here stand for Optional, Transitive and Partial, but not for
1430
   Extended Length. Checking O/T/P bits at once implies, that the attribute
1431
   being diagnosed is defined by RFC as either a "well-known" or an "optional,
1432
   non-transitive" attribute. */
1433
static void
1434
bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args,
1435
      uint8_t desired_flags /* how RFC says it must be */
1436
)
1437
14
{
1438
14
  uint8_t seen = 0, i;
1439
14
  uint8_t real_flags = args->flags;
1440
14
  const uint8_t attr_code = args->type;
1441
1442
14
  desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1443
14
  real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1444
56
  for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1445
42
    if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1446
42
        != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
1447
19
      flog_err(EC_BGP_ATTR_FLAG,
1448
19
         "%s attribute must%s be flagged as \"%s\"",
1449
19
         lookup_msg(attr_str, attr_code, NULL),
1450
19
         CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1451
19
           ? ""
1452
19
           : " not",
1453
19
         attr_flag_str[i].str);
1454
19
      seen = 1;
1455
19
    }
1456
14
  if (!seen) {
1457
0
    zlog_debug(
1458
0
      "Strange, %s called for attr %s, but no problem found with flags (real flags 0x%x, desired 0x%x)",
1459
0
      __func__, lookup_msg(attr_str, attr_code, NULL),
1460
0
      real_flags, desired_flags);
1461
0
  }
1462
14
}
1463
1464
/* Required flags for attributes. EXTLEN will be masked off when testing,
1465
 * as will PARTIAL for optional+transitive attributes.
1466
 */
1467
const uint8_t attr_flags_values[] = {
1468
  [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS,
1469
  [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS,
1470
  [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS,
1471
  [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL,
1472
  [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS,
1473
  [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS,
1474
  [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1475
  [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL,
1476
  [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL,
1477
  [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL,
1478
  [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1479
  [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL,
1480
  [BGP_ATTR_EXT_COMMUNITIES] =
1481
    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1482
  [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1483
  [BGP_ATTR_AS4_AGGREGATOR] =
1484
    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1485
  [BGP_ATTR_PMSI_TUNNEL] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1486
  [BGP_ATTR_LARGE_COMMUNITIES] =
1487
    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1488
  [BGP_ATTR_OTC] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1489
  [BGP_ATTR_PREFIX_SID] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1490
  [BGP_ATTR_IPV6_EXT_COMMUNITIES] =
1491
    BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1492
  [BGP_ATTR_AIGP] = BGP_ATTR_FLAG_OPTIONAL,
1493
};
1494
static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
1495
1496
static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
1497
1.74k
{
1498
1.74k
  uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
1499
1.74k
  const uint8_t flags = args->flags;
1500
1.74k
  const uint8_t attr_code = args->type;
1501
1502
  /* there may be attributes we don't know about */
1503
1.74k
  if (attr_code > attr_flags_values_max)
1504
366
    return false;
1505
1.37k
  if (attr_flags_values[attr_code] == 0)
1506
91
    return false;
1507
1508
  /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1509
   * to
1510
   * 1."
1511
   */
1512
1.28k
  if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
1513
645
      && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
1514
25
    flog_err(
1515
25
      EC_BGP_ATTR_FLAG,
1516
25
      "%s well-known attributes must have transitive flag set (%x)",
1517
25
      lookup_msg(attr_str, attr_code, NULL), flags);
1518
25
    return true;
1519
25
  }
1520
1521
  /* "For well-known attributes and for optional non-transitive
1522
   * attributes,
1523
   *  the Partial bit MUST be set to 0."
1524
   */
1525
1.26k
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
1526
202
    if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) {
1527
1
      flog_err(EC_BGP_ATTR_FLAG,
1528
1
         "%s well-known attribute must NOT have the partial flag set (%x)",
1529
1
         lookup_msg(attr_str, attr_code, NULL), flags);
1530
1
      return true;
1531
1
    }
1532
201
    if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1533
201
        && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) {
1534
3
      flog_err(EC_BGP_ATTR_FLAG,
1535
3
         "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1536
3
         lookup_msg(attr_str, attr_code, NULL), flags);
1537
3
      return true;
1538
3
    }
1539
201
  }
1540
1541
  /* Optional transitive attributes may go through speakers that don't
1542
   * reocgnise them and set the Partial bit.
1543
   */
1544
1.25k
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1545
637
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
1546
263
    SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
1547
1548
1.25k
  if ((flags & ~mask) == attr_flags_values[attr_code])
1549
1.24k
    return false;
1550
1551
14
  bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
1552
14
  return true;
1553
1.25k
}
1554
1555
/* Get origin attribute of the update message. */
1556
static enum bgp_attr_parse_ret
1557
bgp_attr_origin(struct bgp_attr_parser_args *args)
1558
262
{
1559
262
  struct peer *const peer = args->peer;
1560
262
  struct attr *const attr = args->attr;
1561
262
  const bgp_size_t length = args->length;
1562
1563
  /* If any recognized attribute has Attribute Length that conflicts
1564
     with the expected length (based on the attribute type code), then
1565
     the Error Subcode is set to Attribute Length Error.  The Data
1566
     field contains the erroneous attribute (type, length and
1567
     value). */
1568
262
  if (length != 1) {
1569
3
    flog_err(EC_BGP_ATTR_LEN,
1570
3
       "Origin attribute length is not one %d", length);
1571
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1572
3
            args->total);
1573
3
  }
1574
1575
  /* Fetch origin attribute. */
1576
259
  attr->origin = stream_getc(BGP_INPUT(peer));
1577
1578
  /* If the ORIGIN attribute has an undefined value, then the Error
1579
     Subcode is set to Invalid Origin Attribute.  The Data field
1580
     contains the unrecognized attribute (type, length and value). */
1581
259
  if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
1582
87
      && (attr->origin != BGP_ORIGIN_INCOMPLETE)) {
1583
0
    flog_err(EC_BGP_ATTR_ORIGIN,
1584
0
       "Origin attribute value is invalid %d", attr->origin);
1585
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1586
0
            args->total);
1587
0
  }
1588
1589
  /* Set oring attribute flag. */
1590
259
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1591
1592
259
  return 0;
1593
259
}
1594
1595
/* Parse AS path information.  This function is wrapper of
1596
   aspath_parse. */
1597
static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
1598
277
{
1599
277
  struct attr *const attr = args->attr;
1600
277
  struct peer *const peer = args->peer;
1601
277
  const bgp_size_t length = args->length;
1602
277
  enum asnotation_mode asnotation;
1603
1604
277
  asnotation = bgp_get_asnotation(
1605
277
    args->peer && args->peer->bgp ? args->peer->bgp : NULL);
1606
  /*
1607
   * peer with AS4 => will get 4Byte ASnums
1608
   * otherwise, will get 16 Bit
1609
   */
1610
277
  attr->aspath =
1611
277
    aspath_parse(peer->curr, length,
1612
277
           CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
1613
277
             CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
1614
277
           asnotation);
1615
1616
  /* In case of IBGP, length will be zero. */
1617
277
  if (!attr->aspath) {
1618
5
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1619
5
       "Malformed AS path from %s, length is %d", peer->host,
1620
5
       length);
1621
5
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1622
5
            0);
1623
5
  }
1624
1625
  /* Conformant BGP speakers SHOULD NOT send BGP
1626
   * UPDATE messages containing AS_SET or AS_CONFED_SET.  Upon receipt of
1627
   * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1628
   * withdraw" error handling behavior as per [RFC7606].
1629
   */
1630
272
  if (peer->bgp && peer->bgp->reject_as_sets &&
1631
0
      aspath_check_as_sets(attr->aspath)) {
1632
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1633
0
       "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1634
0
       peer);
1635
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1636
0
            0);
1637
0
  }
1638
1639
  /* Set aspath attribute flag. */
1640
272
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1641
1642
272
  return BGP_ATTR_PARSE_PROCEED;
1643
272
}
1644
1645
static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
1646
                 struct attr *const attr)
1647
259
{
1648
  /* These checks were part of bgp_attr_aspath, but with
1649
   * as4 we should to check aspath things when
1650
   * aspath synthesizing with as4_path has already taken place.
1651
   * Otherwise we check ASPATH and use the synthesized thing, and that is
1652
   * not right.
1653
   * So do the checks later, i.e. here
1654
   */
1655
259
  struct aspath *aspath;
1656
1657
  /* Refresh peer's type. If we set e.g.: AS_EXTERNAL/AS_INTERNAL,
1658
   * then peer->sort remains BGP_PEER_EBGP/IBGP, hence we need to
1659
   * have an actual type before checking.
1660
   * This is especially a case for BGP confederation peers, to avoid
1661
   * receiving and treating AS_PATH as malformed.
1662
   */
1663
259
  (void)peer_sort(peer);
1664
1665
  /* Confederation sanity check. */
1666
259
  if ((peer->sort == BGP_PEER_CONFED
1667
0
       && !aspath_left_confed_check(attr->aspath))
1668
259
      || (peer->sort == BGP_PEER_EBGP
1669
259
    && aspath_confed_check(attr->aspath))) {
1670
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH, "Malformed AS path from %s",
1671
0
       peer->host);
1672
0
    return BGP_ATTR_PARSE_WITHDRAW;
1673
0
  }
1674
1675
  /* First AS check for EBGP. */
1676
259
  if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) {
1677
0
    if (peer->sort == BGP_PEER_EBGP
1678
0
        && !aspath_firstas_check(attr->aspath, peer->as)) {
1679
0
      flog_err(EC_BGP_ATTR_FIRST_AS,
1680
0
         "%s incorrect first AS (must be %u)",
1681
0
         peer->host, peer->as);
1682
0
      return BGP_ATTR_PARSE_WITHDRAW;
1683
0
    }
1684
0
  }
1685
1686
  /* Codification of AS 0 Processing */
1687
259
  if (peer->sort == BGP_PEER_EBGP && aspath_check_as_zero(attr->aspath)) {
1688
1
    flog_err(
1689
1
      EC_BGP_ATTR_MAL_AS_PATH,
1690
1
      "Malformed AS path, AS number is 0 in the path from %s",
1691
1
      peer->host);
1692
1
    return BGP_ATTR_PARSE_WITHDRAW;
1693
1
  }
1694
1695
  /* local-as prepend */
1696
258
  if (peer->change_local_as
1697
0
      && !CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) {
1698
0
    aspath = aspath_dup(attr->aspath);
1699
0
    aspath = aspath_add_seq(aspath, peer->change_local_as);
1700
0
    aspath_unintern(&attr->aspath);
1701
0
    attr->aspath = aspath_intern(aspath);
1702
0
  }
1703
1704
258
  return BGP_ATTR_PARSE_PROCEED;
1705
259
}
1706
1707
/* Parse AS4 path information.  This function is another wrapper of
1708
   aspath_parse. */
1709
static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
1710
           struct aspath **as4_path)
1711
41
{
1712
41
  struct peer *const peer = args->peer;
1713
41
  struct attr *const attr = args->attr;
1714
41
  const bgp_size_t length = args->length;
1715
41
  enum asnotation_mode asnotation;
1716
1717
41
  asnotation = bgp_get_asnotation(peer->bgp);
1718
1719
41
  *as4_path = aspath_parse(peer->curr, length, 1, asnotation);
1720
1721
  /* In case of IBGP, length will be zero. */
1722
41
  if (!*as4_path) {
1723
16
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1724
16
       "Malformed AS4 path from %s, length is %d", peer->host,
1725
16
       length);
1726
16
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1727
16
            0);
1728
16
  }
1729
1730
  /* Conformant BGP speakers SHOULD NOT send BGP
1731
   * UPDATE messages containing AS_SET or AS_CONFED_SET.  Upon receipt of
1732
   * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1733
   * withdraw" error handling behavior as per [RFC7606].
1734
   */
1735
25
  if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1736
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1737
0
       "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1738
0
       peer);
1739
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1740
0
            0);
1741
0
  }
1742
1743
  /* Set aspath attribute flag. */
1744
25
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1745
1746
25
  return BGP_ATTR_PARSE_PROCEED;
1747
25
}
1748
1749
/*
1750
 * Check that the nexthop attribute is valid.
1751
 */
1752
enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
1753
                 struct attr *attr)
1754
1
{
1755
1
  struct bgp *bgp = peer->bgp;
1756
1757
1
  if (ipv4_martian(&attr->nexthop) && !bgp->allow_martian) {
1758
1
    uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
1759
1760
1
    flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %pI4",
1761
1
       &attr->nexthop);
1762
1
    data[0] = BGP_ATTR_FLAG_TRANS;
1763
1
    data[1] = BGP_ATTR_NEXT_HOP;
1764
1
    data[2] = BGP_ATTR_NHLEN_IPV4;
1765
1
    memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4);
1766
1
    bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
1767
1
            BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
1768
1
            data, 7);
1769
1
    return BGP_ATTR_PARSE_ERROR;
1770
1
  }
1771
1772
0
  return BGP_ATTR_PARSE_PROCEED;
1773
1
}
1774
1775
/* Nexthop attribute. */
1776
static enum bgp_attr_parse_ret
1777
bgp_attr_nexthop(struct bgp_attr_parser_args *args)
1778
64
{
1779
64
  struct peer *const peer = args->peer;
1780
64
  struct attr *const attr = args->attr;
1781
64
  const bgp_size_t length = args->length;
1782
1783
  /* Check nexthop attribute length. */
1784
64
  if (length != 4) {
1785
1
    flog_err(EC_BGP_ATTR_LEN,
1786
1
       "Nexthop attribute length isn't four [%d]", length);
1787
1788
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1789
1
            args->total);
1790
1
  }
1791
1792
63
  attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
1793
63
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1794
1795
63
  return BGP_ATTR_PARSE_PROCEED;
1796
64
}
1797
1798
/* MED atrribute. */
1799
static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
1800
7
{
1801
7
  struct peer *const peer = args->peer;
1802
7
  struct attr *const attr = args->attr;
1803
7
  const bgp_size_t length = args->length;
1804
1805
  /* Length check. */
1806
7
  if (length != 4) {
1807
3
    flog_err(EC_BGP_ATTR_LEN,
1808
3
       "MED attribute length isn't four [%d]", length);
1809
1810
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1811
3
            args->total);
1812
3
  }
1813
1814
4
  attr->med = stream_getl(peer->curr);
1815
1816
4
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1817
1818
4
  return BGP_ATTR_PARSE_PROCEED;
1819
7
}
1820
1821
/* Local preference attribute. */
1822
static enum bgp_attr_parse_ret
1823
bgp_attr_local_pref(struct bgp_attr_parser_args *args)
1824
3
{
1825
3
  struct peer *const peer = args->peer;
1826
3
  struct attr *const attr = args->attr;
1827
3
  const bgp_size_t length = args->length;
1828
1829
  /* if received from an internal neighbor, it SHALL be considered
1830
   * malformed if its length is not equal to 4. If malformed, the
1831
   * UPDATE message SHALL be handled using the approach of "treat-as-
1832
   * withdraw".
1833
   */
1834
3
  if (peer->sort == BGP_PEER_IBGP && length != 4) {
1835
0
    flog_err(EC_BGP_ATTR_LEN,
1836
0
       "LOCAL_PREF attribute length isn't 4 [%u]", length);
1837
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1838
0
            args->total);
1839
0
  }
1840
1841
  /* If it is contained in an UPDATE message that is received from an
1842
     external peer, then this attribute MUST be ignored by the
1843
     receiving speaker. */
1844
3
  if (peer->sort == BGP_PEER_EBGP) {
1845
3
    STREAM_FORWARD_GETP(peer->curr, length);
1846
3
    return BGP_ATTR_PARSE_PROCEED;
1847
3
  }
1848
1849
0
  STREAM_GETL(peer->curr, attr->local_pref);
1850
1851
  /* Set the local-pref flag. */
1852
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1853
1854
0
  return BGP_ATTR_PARSE_PROCEED;
1855
1856
0
stream_failure:
1857
0
  return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1858
0
          args->total);
1859
0
}
1860
1861
/* Atomic aggregate. */
1862
static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
1863
7
{
1864
7
  struct peer *const peer = args->peer;
1865
7
  struct attr *const attr = args->attr;
1866
7
  const bgp_size_t length = args->length;
1867
1868
  /* Length check. */
1869
7
  if (length != 0) {
1870
3
    flog_err(EC_BGP_ATTR_LEN,
1871
3
       "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1872
3
       length);
1873
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1874
3
            args->total);
1875
3
  }
1876
1877
4
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1878
0
    goto atomic_ignore;
1879
1880
  /* Set atomic aggregate flag. */
1881
4
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1882
1883
4
  return BGP_ATTR_PARSE_PROCEED;
1884
1885
0
atomic_ignore:
1886
0
  stream_forward_getp(peer->curr, length);
1887
1888
0
  return bgp_attr_ignore(peer, args->type);
1889
4
}
1890
1891
/* Aggregator attribute */
1892
static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
1893
2
{
1894
2
  struct peer *const peer = args->peer;
1895
2
  struct attr *const attr = args->attr;
1896
2
  const bgp_size_t length = args->length;
1897
2
  as_t aggregator_as;
1898
1899
2
  int wantedlen = 6;
1900
1901
  /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1902
2
  if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1903
2
      && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV))
1904
2
    wantedlen = 8;
1905
1906
2
  if (length != wantedlen) {
1907
2
    flog_err(EC_BGP_ATTR_LEN,
1908
2
       "AGGREGATOR attribute length isn't %u [%u]", wantedlen,
1909
2
       length);
1910
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1911
2
            args->total);
1912
2
  }
1913
1914
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1915
0
    goto aggregator_ignore;
1916
1917
0
  if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
1918
0
    aggregator_as = stream_getl(peer->curr);
1919
0
  else
1920
0
    aggregator_as = stream_getw(peer->curr);
1921
1922
0
  attr->aggregator_as = aggregator_as;
1923
0
  attr->aggregator_addr.s_addr = stream_get_ipv4(peer->curr);
1924
1925
  /* Codification of AS 0 Processing */
1926
0
  if (aggregator_as == BGP_AS_ZERO) {
1927
0
    flog_err(EC_BGP_ATTR_LEN,
1928
0
       "%s: AGGREGATOR AS number is 0 for aspath: %s",
1929
0
       peer->host, aspath_print(attr->aspath));
1930
1931
0
    if (bgp_debug_update(peer, NULL, NULL, 1)) {
1932
0
      char attr_str[BUFSIZ] = {0};
1933
1934
0
      bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1935
1936
0
      zlog_debug("%s: attributes: %s", __func__, attr_str);
1937
0
    }
1938
0
  } else {
1939
0
    attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
1940
0
  }
1941
1942
0
  return BGP_ATTR_PARSE_PROCEED;
1943
1944
0
aggregator_ignore:
1945
0
  stream_forward_getp(peer->curr, length);
1946
1947
0
  return bgp_attr_ignore(peer, args->type);
1948
0
}
1949
1950
/* New Aggregator attribute */
1951
static enum bgp_attr_parse_ret
1952
bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
1953
      as_t *as4_aggregator_as,
1954
      struct in_addr *as4_aggregator_addr)
1955
2
{
1956
2
  struct peer *const peer = args->peer;
1957
2
  struct attr *const attr = args->attr;
1958
2
  const bgp_size_t length = args->length;
1959
2
  as_t aggregator_as;
1960
1961
2
  if (length != 8) {
1962
2
    flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1963
2
       length);
1964
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1965
2
            0);
1966
2
  }
1967
1968
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1969
0
    goto as4_aggregator_ignore;
1970
1971
0
  aggregator_as = stream_getl(peer->curr);
1972
1973
0
  *as4_aggregator_as = aggregator_as;
1974
0
  as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr);
1975
1976
  /* Codification of AS 0 Processing */
1977
0
  if (aggregator_as == BGP_AS_ZERO) {
1978
0
    flog_err(EC_BGP_ATTR_LEN,
1979
0
       "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1980
0
       peer->host, aspath_print(attr->aspath));
1981
1982
0
    if (bgp_debug_update(peer, NULL, NULL, 1)) {
1983
0
      char attr_str[BUFSIZ] = {0};
1984
1985
0
      bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1986
1987
0
      zlog_debug("%s: attributes: %s", __func__, attr_str);
1988
0
    }
1989
0
  } else {
1990
0
    attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
1991
0
  }
1992
1993
0
  return BGP_ATTR_PARSE_PROCEED;
1994
1995
0
as4_aggregator_ignore:
1996
0
  stream_forward_getp(peer->curr, length);
1997
1998
0
  return bgp_attr_ignore(peer, args->type);
1999
0
}
2000
2001
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
2002
 */
2003
static enum bgp_attr_parse_ret
2004
bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
2005
       struct aspath *as4_path, as_t as4_aggregator,
2006
       struct in_addr *as4_aggregator_addr)
2007
259
{
2008
259
  int ignore_as4_path = 0;
2009
259
  struct aspath *newpath;
2010
2011
259
  if (!attr->aspath) {
2012
    /* NULL aspath shouldn't be possible as bgp_attr_parse should
2013
     * have
2014
     * checked that all well-known, mandatory attributes were
2015
     * present.
2016
     *
2017
     * Can only be a problem with peer itself - hard error
2018
     */
2019
0
    return BGP_ATTR_PARSE_ERROR;
2020
0
  }
2021
2022
259
  if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) {
2023
    /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR
2024
     * if given.
2025
     * It is worth a warning though, because the peer really
2026
     * should not send them
2027
     */
2028
259
    if (BGP_DEBUG(as4, AS4)) {
2029
0
      if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
2030
0
        zlog_debug("[AS4] %s %s AS4_PATH", peer->host,
2031
0
             "AS4 capable peer, yet it sent");
2032
2033
0
      if (attr->flag
2034
0
          & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
2035
0
        zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
2036
0
             peer->host,
2037
0
             "AS4 capable peer, yet it sent");
2038
0
    }
2039
2040
259
    return BGP_ATTR_PARSE_PROCEED;
2041
259
  }
2042
2043
  /* We have a asn16 peer.  First, look for AS4_AGGREGATOR
2044
   * because that may override AS4_PATH
2045
   */
2046
0
  if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) {
2047
0
    if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
2048
      /* received both.
2049
       * if the as_number in aggregator is not AS_TRANS,
2050
       *  then AS4_AGGREGATOR and AS4_PATH shall be ignored
2051
       *        and the Aggregator shall be taken as
2052
       *        info on the aggregating node, and the AS_PATH
2053
       *        shall be taken as the AS_PATH
2054
       *  otherwise
2055
       *        the Aggregator shall be ignored and the
2056
       *        AS4_AGGREGATOR shall be taken as the
2057
       *        Aggregating node and the AS_PATH is to be
2058
       *        constructed "as in all other cases"
2059
       */
2060
0
      if (attr->aggregator_as != BGP_AS_TRANS) {
2061
        /* ignore */
2062
0
        if (BGP_DEBUG(as4, AS4))
2063
0
          zlog_debug(
2064
0
            "[AS4] %s BGP not AS4 capable peer send AGGREGATOR != AS_TRANS and AS4_AGGREGATOR, so ignore AS4_AGGREGATOR and AS4_PATH",
2065
0
            peer->host);
2066
0
        ignore_as4_path = 1;
2067
0
      } else {
2068
        /* "New_aggregator shall be taken as aggregator"
2069
         */
2070
0
        attr->aggregator_as = as4_aggregator;
2071
0
        attr->aggregator_addr.s_addr =
2072
0
          as4_aggregator_addr->s_addr;
2073
0
      }
2074
0
    } else {
2075
      /* We received a AS4_AGGREGATOR but no AGGREGATOR.
2076
       * That is bogus - but reading the conditions
2077
       * we have to handle AS4_AGGREGATOR as if it were
2078
       * AGGREGATOR in that case
2079
       */
2080
0
      if (BGP_DEBUG(as4, AS4))
2081
0
        zlog_debug(
2082
0
          "[AS4] %s BGP not AS4 capable peer send AS4_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there",
2083
0
          peer->host);
2084
0
      attr->aggregator_as = as4_aggregator;
2085
      /* sweep it under the carpet and simulate a "good"
2086
       * AGGREGATOR */
2087
0
      attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
2088
0
    }
2089
0
  }
2090
2091
  /* need to reconcile NEW_AS_PATH and AS_PATH */
2092
0
  if (!ignore_as4_path
2093
0
      && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
2094
0
    newpath = aspath_reconcile_as4(attr->aspath, as4_path);
2095
0
    if (!newpath)
2096
0
      return BGP_ATTR_PARSE_ERROR;
2097
2098
0
    aspath_unintern(&attr->aspath);
2099
0
    attr->aspath = aspath_intern(newpath);
2100
0
  }
2101
0
  return BGP_ATTR_PARSE_PROCEED;
2102
0
}
2103
2104
/* Community attribute. */
2105
static enum bgp_attr_parse_ret
2106
bgp_attr_community(struct bgp_attr_parser_args *args)
2107
25
{
2108
25
  struct peer *const peer = args->peer;
2109
25
  struct attr *const attr = args->attr;
2110
25
  const bgp_size_t length = args->length;
2111
2112
25
  if (length == 0) {
2113
0
    bgp_attr_set_community(attr, NULL);
2114
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2115
0
            args->total);
2116
0
  }
2117
2118
25
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2119
0
    goto community_ignore;
2120
2121
25
  bgp_attr_set_community(
2122
25
    attr,
2123
25
    community_parse((uint32_t *)stream_pnt(peer->curr), length));
2124
2125
  /* XXX: fix community_parse to use stream API and remove this */
2126
25
  stream_forward_getp(peer->curr, length);
2127
2128
  /* The Community attribute SHALL be considered malformed if its
2129
   * length is not a non-zero multiple of 4.
2130
   */
2131
25
  if (!bgp_attr_get_community(attr))
2132
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2133
0
            args->total);
2134
2135
25
  return BGP_ATTR_PARSE_PROCEED;
2136
2137
0
community_ignore:
2138
0
  stream_forward_getp(peer->curr, length);
2139
2140
0
  return bgp_attr_ignore(peer, args->type);
2141
25
}
2142
2143
/* Originator ID attribute. */
2144
static enum bgp_attr_parse_ret
2145
bgp_attr_originator_id(struct bgp_attr_parser_args *args)
2146
8
{
2147
8
  struct peer *const peer = args->peer;
2148
8
  struct attr *const attr = args->attr;
2149
8
  const bgp_size_t length = args->length;
2150
2151
  /* if received from an internal neighbor, it SHALL be considered
2152
   * malformed if its length is not equal to 4. If malformed, the
2153
   * UPDATE message SHALL be handled using the approach of "treat-as-
2154
   * withdraw".
2155
   */
2156
8
  if (length != 4) {
2157
0
    flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
2158
0
       length);
2159
2160
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2161
0
            args->total);
2162
0
  }
2163
2164
8
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2165
0
    goto originator_id_ignore;
2166
2167
8
  attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
2168
2169
8
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2170
2171
8
  return BGP_ATTR_PARSE_PROCEED;
2172
2173
0
originator_id_ignore:
2174
0
  stream_forward_getp(peer->curr, length);
2175
2176
0
  return bgp_attr_ignore(peer, args->type);
2177
8
}
2178
2179
/* Cluster list attribute. */
2180
static enum bgp_attr_parse_ret
2181
bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
2182
20
{
2183
20
  struct peer *const peer = args->peer;
2184
20
  struct attr *const attr = args->attr;
2185
20
  const bgp_size_t length = args->length;
2186
2187
  /* if received from an internal neighbor, it SHALL be considered
2188
   * malformed if its length is not a non-zero multiple of 4.  If
2189
   * malformed, the UPDATE message SHALL be handled using the approach
2190
   * of "treat-as-withdraw".
2191
   */
2192
20
  if (length == 0 || length % 4) {
2193
0
    flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
2194
2195
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2196
0
            args->total);
2197
0
  }
2198
2199
20
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2200
0
    goto cluster_list_ignore;
2201
2202
20
  bgp_attr_set_cluster(
2203
20
    attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2204
20
            length));
2205
2206
  /* XXX: Fix cluster_parse to use stream API and then remove this */
2207
20
  stream_forward_getp(peer->curr, length);
2208
2209
20
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
2210
2211
20
  return BGP_ATTR_PARSE_PROCEED;
2212
2213
0
cluster_list_ignore:
2214
0
  stream_forward_getp(peer->curr, length);
2215
2216
0
  return bgp_attr_ignore(peer, args->type);
2217
20
}
2218
2219
/* Multiprotocol reachability information parse. */
2220
int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
2221
           struct bgp_nlri *mp_update)
2222
323
{
2223
323
  iana_afi_t pkt_afi;
2224
323
  afi_t afi;
2225
323
  iana_safi_t pkt_safi;
2226
323
  safi_t safi;
2227
323
  bgp_size_t nlri_len;
2228
323
  size_t start;
2229
323
  struct stream *s;
2230
323
  struct peer *const peer = args->peer;
2231
323
  struct attr *const attr = args->attr;
2232
323
  const bgp_size_t length = args->length;
2233
2234
  /* Set end of packet. */
2235
323
  s = BGP_INPUT(peer);
2236
323
  start = stream_get_getp(s);
2237
2238
/* safe to read statically sized header? */
2239
323
#define BGP_MP_REACH_MIN_SIZE 5
2240
967
#define LEN_LEFT  (length - (stream_get_getp(s) - start))
2241
323
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
2242
0
    zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2243
0
        __func__, peer->host, (unsigned long)length);
2244
0
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2245
0
  }
2246
2247
  /* Load AFI, SAFI. */
2248
323
  pkt_afi = stream_getw(s);
2249
323
  pkt_safi = stream_getc(s);
2250
2251
  /* Convert AFI, SAFI to internal values, check. */
2252
323
  if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2253
    /* Log if AFI or SAFI is unrecognized. This is not an error
2254
     * unless
2255
     * the attribute is otherwise malformed.
2256
     */
2257
0
    if (bgp_debug_update(peer, NULL, NULL, 0))
2258
0
      zlog_debug(
2259
0
        "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2260
0
        peer->host, iana_afi2str(pkt_afi),
2261
0
        iana_safi2str(pkt_safi));
2262
0
    return BGP_ATTR_PARSE_ERROR;
2263
0
  }
2264
2265
  /* Get nexthop length. */
2266
323
  attr->mp_nexthop_len = stream_getc(s);
2267
2268
323
  if (LEN_LEFT < attr->mp_nexthop_len) {
2269
0
    zlog_info(
2270
0
      "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2271
0
      __func__, peer->host, attr->mp_nexthop_len);
2272
0
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2273
0
  }
2274
2275
  /* Nexthop length check. */
2276
323
  switch (attr->mp_nexthop_len) {
2277
0
  case 0:
2278
0
    if (safi != SAFI_FLOWSPEC) {
2279
0
      zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2280
0
          __func__, peer->host, attr->mp_nexthop_len);
2281
0
      return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2282
0
    }
2283
0
    break;
2284
14
  case BGP_ATTR_NHLEN_VPNV4:
2285
14
    stream_getl(s); /* RD high */
2286
14
    stream_getl(s); /* RD low */
2287
        /*
2288
         * NOTE: intentional fall through
2289
         * - for consistency in rx processing
2290
         *
2291
         * The following comment is to signal GCC this intention
2292
         * and suppress the warning
2293
         */
2294
  /* FALLTHRU */
2295
63
  case BGP_ATTR_NHLEN_IPV4:
2296
63
    stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2297
    /* Probably needed for RFC 2283 */
2298
63
    if (attr->nexthop.s_addr == INADDR_ANY)
2299
56
      memcpy(&attr->nexthop.s_addr,
2300
56
             &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2301
63
    break;
2302
259
  case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2303
259
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2304
259
    if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) {
2305
0
      stream_getl(s); /* RD high */
2306
0
      stream_getl(s); /* RD low */
2307
0
    }
2308
259
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2309
259
    if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2310
0
      if (!peer->nexthop.ifp) {
2311
0
        zlog_warn("%s sent a v6 global attribute but address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2312
0
            peer->host);
2313
0
        return BGP_ATTR_PARSE_WITHDRAW;
2314
0
      }
2315
0
      attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2316
0
    }
2317
259
    break;
2318
259
  case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2319
0
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
2320
0
    if (attr->mp_nexthop_len
2321
0
        == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2322
0
      stream_getl(s); /* RD high */
2323
0
      stream_getl(s); /* RD low */
2324
0
    }
2325
0
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2326
0
    if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2327
0
      if (!peer->nexthop.ifp) {
2328
0
        zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2329
0
            peer->host);
2330
0
        return BGP_ATTR_PARSE_WITHDRAW;
2331
0
      }
2332
0
      attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2333
0
    }
2334
0
    if (attr->mp_nexthop_len
2335
0
        == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2336
0
      stream_getl(s); /* RD high */
2337
0
      stream_getl(s); /* RD low */
2338
0
    }
2339
0
    stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
2340
0
    if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
2341
0
      if (bgp_debug_update(peer, NULL, NULL, 1))
2342
0
        zlog_debug(
2343
0
          "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2344
0
          peer->host, &attr->mp_nexthop_global,
2345
0
          &attr->mp_nexthop_local);
2346
2347
0
      attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
2348
0
    }
2349
0
    if (!peer->nexthop.ifp) {
2350
0
      zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2351
0
          peer->host);
2352
0
      return BGP_ATTR_PARSE_WITHDRAW;
2353
0
    }
2354
0
    attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
2355
0
    break;
2356
1
  default:
2357
1
    zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2358
1
        __func__, peer->host, attr->mp_nexthop_len);
2359
1
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2360
323
  }
2361
2362
322
  if (!LEN_LEFT) {
2363
0
    zlog_info("%s: %s sent SNPA which couldn't be read",
2364
0
        __func__, peer->host);
2365
0
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2366
0
  }
2367
2368
322
  {
2369
322
    uint8_t val;
2370
322
    if ((val = stream_getc(s)))
2371
208
      flog_warn(
2372
322
        EC_BGP_DEFUNCT_SNPA_LEN,
2373
322
        "%s sent non-zero value, %u, for defunct SNPA-length field",
2374
322
        peer->host, val);
2375
322
  }
2376
2377
  /* must have nrli_len, what is left of the attribute */
2378
322
  nlri_len = LEN_LEFT;
2379
322
  if (nlri_len > STREAM_READABLE(s)) {
2380
0
    zlog_info("%s: %s sent MP_REACH_NLRI which couldn't be read",
2381
0
        __func__, peer->host);
2382
0
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2383
0
  }
2384
2385
322
  if (!nlri_len) {
2386
39
    zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2387
39
        __func__, peer->host);
2388
2389
39
    mp_update->afi = afi;
2390
39
    mp_update->safi = safi;
2391
39
    return BGP_ATTR_PARSE_EOR;
2392
39
  }
2393
2394
283
  mp_update->afi = afi;
2395
283
  mp_update->safi = safi;
2396
283
  mp_update->nlri = stream_pnt(s);
2397
283
  mp_update->length = nlri_len;
2398
2399
283
  stream_forward_getp(s, nlri_len);
2400
2401
283
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2402
2403
283
  return BGP_ATTR_PARSE_PROCEED;
2404
322
#undef LEN_LEFT
2405
322
}
2406
2407
/* Multiprotocol unreachable parse */
2408
int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2409
       struct bgp_nlri *mp_withdraw)
2410
12
{
2411
12
  struct stream *s;
2412
12
  iana_afi_t pkt_afi;
2413
12
  afi_t afi;
2414
12
  iana_safi_t pkt_safi;
2415
12
  safi_t safi;
2416
12
  uint16_t withdraw_len;
2417
12
  struct peer *const peer = args->peer;
2418
12
  struct attr *const attr = args->attr;
2419
12
  const bgp_size_t length = args->length;
2420
2421
12
  s = peer->curr;
2422
2423
21
#define BGP_MP_UNREACH_MIN_SIZE 3
2424
12
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2425
1
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2426
2427
11
  pkt_afi = stream_getw(s);
2428
11
  pkt_safi = stream_getc(s);
2429
2430
  /* Convert AFI, SAFI to internal values, check. */
2431
11
  if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2432
    /* Log if AFI or SAFI is unrecognized. This is not an error
2433
     * unless
2434
     * the attribute is otherwise malformed.
2435
     */
2436
2
    if (bgp_debug_update(peer, NULL, NULL, 0))
2437
0
      zlog_debug(
2438
2
        "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2439
2
        peer->host, iana_afi2str(pkt_afi),
2440
2
        iana_safi2str(pkt_safi));
2441
2
    return BGP_ATTR_PARSE_ERROR;
2442
2
  }
2443
2444
9
  withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
2445
2446
9
  mp_withdraw->afi = afi;
2447
9
  mp_withdraw->safi = safi;
2448
9
  mp_withdraw->nlri = stream_pnt(s);
2449
9
  mp_withdraw->length = withdraw_len;
2450
2451
9
  stream_forward_getp(s, withdraw_len);
2452
2453
9
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
2454
2455
9
  return BGP_ATTR_PARSE_PROCEED;
2456
11
}
2457
2458
/* Large Community attribute. */
2459
static enum bgp_attr_parse_ret
2460
bgp_attr_large_community(struct bgp_attr_parser_args *args)
2461
12
{
2462
12
  struct peer *const peer = args->peer;
2463
12
  struct attr *const attr = args->attr;
2464
12
  const bgp_size_t length = args->length;
2465
2466
  /*
2467
   * Large community follows new attribute format.
2468
   */
2469
12
  if (length == 0) {
2470
0
    bgp_attr_set_lcommunity(attr, NULL);
2471
    /* Empty extcomm doesn't seem to be invalid per se */
2472
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2473
0
            args->total);
2474
0
  }
2475
2476
12
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2477
0
    goto large_community_ignore;
2478
2479
12
  bgp_attr_set_lcommunity(
2480
12
    attr, lcommunity_parse(stream_pnt(peer->curr), length));
2481
  /* XXX: fix ecommunity_parse to use stream API */
2482
12
  stream_forward_getp(peer->curr, length);
2483
2484
12
  if (!bgp_attr_get_lcommunity(attr))
2485
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2486
2
            args->total);
2487
2488
10
  return BGP_ATTR_PARSE_PROCEED;
2489
2490
0
large_community_ignore:
2491
0
  stream_forward_getp(peer->curr, length);
2492
2493
0
  return bgp_attr_ignore(peer, args->type);
2494
12
}
2495
2496
/* Extended Community attribute. */
2497
static enum bgp_attr_parse_ret
2498
bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
2499
110
{
2500
110
  struct peer *const peer = args->peer;
2501
110
  struct attr *const attr = args->attr;
2502
110
  const bgp_size_t length = args->length;
2503
110
  uint8_t sticky = 0;
2504
110
  bool proxy = false;
2505
110
  struct ecommunity *ecomm;
2506
2507
110
  if (length == 0) {
2508
0
    bgp_attr_set_ecommunity(attr, NULL);
2509
    /* Empty extcomm doesn't seem to be invalid per se */
2510
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2511
0
            args->total);
2512
0
  }
2513
2514
110
  ecomm = ecommunity_parse(
2515
110
    stream_pnt(peer->curr), length,
2516
110
    CHECK_FLAG(peer->flags,
2517
110
         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2518
110
  bgp_attr_set_ecommunity(attr, ecomm);
2519
  /* XXX: fix ecommunity_parse to use stream API */
2520
110
  stream_forward_getp(peer->curr, length);
2521
2522
  /* The Extended Community attribute SHALL be considered malformed if
2523
   * its length is not a non-zero multiple of 8.
2524
   */
2525
110
  if (!bgp_attr_get_ecommunity(attr))
2526
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2527
1
            args->total);
2528
2529
  /* Extract DF election preference and  mobility sequence number */
2530
109
  attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
2531
2532
  /* Extract MAC mobility sequence number, if any. */
2533
109
  attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
2534
109
  attr->sticky = sticky;
2535
2536
  /* Check if this is a Gateway MAC-IP advertisement */
2537
109
  attr->default_gw = bgp_attr_default_gw(attr);
2538
2539
  /* Handle scenario where router flag ecommunity is not
2540
   * set but default gw ext community is present.
2541
   * Use default gateway, set and propogate R-bit.
2542
   */
2543
109
  if (attr->default_gw)
2544
5
    attr->router_flag = 1;
2545
2546
  /* Check EVPN Neighbor advertisement flags, R-bit */
2547
109
  bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
2548
109
  if (proxy)
2549
4
    attr->es_flags |= ATTR_ES_PROXY_ADVERT;
2550
2551
  /* Extract the Rmac, if any */
2552
109
  if (bgp_attr_rmac(attr, &attr->rmac)) {
2553
6
    if (bgp_debug_update(peer, NULL, NULL, 1)
2554
0
        && bgp_mac_exist(&attr->rmac))
2555
0
      zlog_debug("%s: router mac %pEA is self mac", __func__,
2556
6
           &attr->rmac);
2557
6
  }
2558
2559
  /* Get the tunnel type from encap extended community */
2560
109
  bgp_attr_extcom_tunnel_type(attr,
2561
109
    (bgp_encap_types *)&attr->encap_tunneltype);
2562
2563
  /* Extract link bandwidth, if any. */
2564
109
  (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr),
2565
109
          &attr->link_bw);
2566
2567
109
  return BGP_ATTR_PARSE_PROCEED;
2568
110
}
2569
2570
/* IPv6 Extended Community attribute. */
2571
static enum bgp_attr_parse_ret
2572
bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
2573
29
{
2574
29
  struct peer *const peer = args->peer;
2575
29
  struct attr *const attr = args->attr;
2576
29
  const bgp_size_t length = args->length;
2577
29
  struct ecommunity *ipv6_ecomm = NULL;
2578
2579
29
  if (length == 0) {
2580
0
    bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2581
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2582
0
            args->total);
2583
0
  }
2584
2585
29
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2586
0
    goto ipv6_ext_community_ignore;
2587
2588
29
  ipv6_ecomm = ecommunity_parse_ipv6(
2589
29
    stream_pnt(peer->curr), length,
2590
29
    CHECK_FLAG(peer->flags,
2591
29
         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2592
29
  bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2593
2594
  /* XXX: fix ecommunity_parse to use stream API */
2595
29
  stream_forward_getp(peer->curr, length);
2596
2597
29
  if (!ipv6_ecomm)
2598
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2599
3
            args->total);
2600
2601
26
  return BGP_ATTR_PARSE_PROCEED;
2602
2603
0
ipv6_ext_community_ignore:
2604
0
  stream_forward_getp(peer->curr, length);
2605
2606
0
  return bgp_attr_ignore(peer, args->type);
2607
29
}
2608
2609
/* Parse Tunnel Encap attribute in an UPDATE */
2610
static int bgp_attr_encap(struct bgp_attr_parser_args *args)
2611
6
{
2612
6
  uint16_t tunneltype = 0;
2613
6
  struct peer *const peer = args->peer;
2614
6
  struct attr *const attr = args->attr;
2615
6
  bgp_size_t length = args->length;
2616
6
  uint8_t type = args->type;
2617
6
  uint8_t flag = args->flags;
2618
2619
6
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2620
6
      || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
2621
0
    zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d",
2622
0
       flag);
2623
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2624
0
            args->total);
2625
0
  }
2626
2627
6
  if (BGP_ATTR_ENCAP == type) {
2628
    /* read outer TLV type and length */
2629
6
    uint16_t tlv_length;
2630
2631
6
    if (length < 4) {
2632
0
      zlog_err(
2633
0
        "Tunnel Encap attribute not long enough to contain outer T,L");
2634
0
      return bgp_attr_malformed(args,
2635
0
              BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2636
0
              args->total);
2637
0
    }
2638
6
    tunneltype = stream_getw(BGP_INPUT(peer));
2639
6
    tlv_length = stream_getw(BGP_INPUT(peer));
2640
6
    length -= 4;
2641
2642
6
    if (tlv_length != length) {
2643
6
      zlog_info("%s: tlv_length(%d) != length(%d)",
2644
6
          __func__, tlv_length, length);
2645
6
    }
2646
6
  }
2647
2648
542
  while (length >= 4) {
2649
541
    uint16_t subtype = 0;
2650
541
    uint16_t sublength = 0;
2651
541
    struct bgp_attr_encap_subtlv *tlv;
2652
2653
541
    if (BGP_ATTR_ENCAP == type) {
2654
541
      subtype = stream_getc(BGP_INPUT(peer));
2655
541
      sublength = stream_getc(BGP_INPUT(peer));
2656
541
      length -= 2;
2657
541
#ifdef ENABLE_BGP_VNC
2658
541
    } else {
2659
0
      subtype = stream_getw(BGP_INPUT(peer));
2660
0
      sublength = stream_getw(BGP_INPUT(peer));
2661
0
      length -= 4;
2662
0
#endif
2663
0
    }
2664
2665
541
    if (sublength > length) {
2666
5
      zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2667
5
         sublength, length);
2668
5
      return bgp_attr_malformed(args,
2669
5
              BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2670
5
              args->total);
2671
5
    }
2672
2673
    /* alloc and copy sub-tlv */
2674
    /* TBD make sure these are freed when attributes are released */
2675
536
    tlv = XCALLOC(MTYPE_ENCAP_TLV,
2676
536
            sizeof(struct bgp_attr_encap_subtlv) + sublength);
2677
536
    tlv->type = subtype;
2678
536
    tlv->length = sublength;
2679
536
    stream_get(tlv->value, peer->curr, sublength);
2680
536
    length -= sublength;
2681
2682
    /* attach tlv to encap chain */
2683
536
    if (BGP_ATTR_ENCAP == type) {
2684
536
      struct bgp_attr_encap_subtlv *stlv_last;
2685
536
      for (stlv_last = attr->encap_subtlvs;
2686
35.2k
           stlv_last && stlv_last->next;
2687
34.7k
           stlv_last = stlv_last->next)
2688
34.7k
        ;
2689
536
      if (stlv_last) {
2690
530
        stlv_last->next = tlv;
2691
530
      } else {
2692
6
        attr->encap_subtlvs = tlv;
2693
6
      }
2694
536
#ifdef ENABLE_BGP_VNC
2695
536
    } else {
2696
0
      struct bgp_attr_encap_subtlv *stlv_last;
2697
0
      struct bgp_attr_encap_subtlv *vnc_subtlvs =
2698
0
        bgp_attr_get_vnc_subtlvs(attr);
2699
2700
0
      for (stlv_last = vnc_subtlvs;
2701
0
           stlv_last && stlv_last->next;
2702
0
           stlv_last = stlv_last->next)
2703
0
        ;
2704
0
      if (stlv_last)
2705
0
        stlv_last->next = tlv;
2706
0
      else
2707
0
        bgp_attr_set_vnc_subtlvs(attr, tlv);
2708
0
#endif
2709
0
    }
2710
536
  }
2711
2712
1
  if (BGP_ATTR_ENCAP == type) {
2713
1
    attr->encap_tunneltype = tunneltype;
2714
1
  }
2715
2716
1
  if (length) {
2717
    /* spurious leftover data */
2718
0
    zlog_err("Tunnel Encap attribute length is bad: %d leftover octets",
2719
0
       length);
2720
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2721
0
            args->total);
2722
0
  }
2723
2724
1
  return 0;
2725
1
}
2726
2727
2728
/* SRv6 Service Data Sub-Sub-TLV attribute
2729
 * draft-ietf-bess-srv6-services-07
2730
 */
2731
static enum bgp_attr_parse_ret
2732
bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
2733
7
{
2734
7
  struct peer *const peer = args->peer;
2735
7
  struct attr *const attr = args->attr;
2736
7
  uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2737
7
    transposition_len, transposition_offset;
2738
7
  uint16_t length;
2739
7
  size_t headersz = sizeof(type) + sizeof(length);
2740
2741
7
  if (STREAM_READABLE(peer->curr) < headersz) {
2742
0
    flog_err(
2743
0
      EC_BGP_ATTR_LEN,
2744
0
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2745
0
      headersz, STREAM_READABLE(peer->curr));
2746
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2747
0
            args->total);
2748
0
  }
2749
2750
7
  type = stream_getc(peer->curr);
2751
7
  length = stream_getw(peer->curr);
2752
2753
7
  if (STREAM_READABLE(peer->curr) < length) {
2754
0
    flog_err(
2755
0
      EC_BGP_ATTR_LEN,
2756
0
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2757
0
      length, STREAM_READABLE(peer->curr));
2758
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2759
0
            args->total);
2760
0
  }
2761
2762
7
  if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2763
3
    flog_err(
2764
3
      EC_BGP_ATTR_LEN,
2765
3
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2766
3
      BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2767
3
      length);
2768
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2769
3
            args->total);
2770
3
  }
2771
2772
4
  if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
2773
2
    if (STREAM_READABLE(peer->curr) <
2774
2
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2775
0
      flog_err(
2776
0
        EC_BGP_ATTR_LEN,
2777
0
        "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2778
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2779
0
        STREAM_READABLE(peer->curr));
2780
0
      return bgp_attr_malformed(
2781
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2782
0
        args->total);
2783
0
    }
2784
2785
2
    loc_block_len = stream_getc(peer->curr);
2786
2
    loc_node_len = stream_getc(peer->curr);
2787
2
    func_len = stream_getc(peer->curr);
2788
2
    arg_len = stream_getc(peer->curr);
2789
2
    transposition_len = stream_getc(peer->curr);
2790
2
    transposition_offset = stream_getc(peer->curr);
2791
2792
    /* Log SRv6 Service Data Sub-Sub-TLV */
2793
2
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2794
0
      zlog_debug(
2795
0
        "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2796
0
        __func__, loc_block_len, loc_node_len, func_len,
2797
0
        arg_len, transposition_len,
2798
0
        transposition_offset);
2799
0
    }
2800
2801
2
    attr->srv6_l3vpn->loc_block_len = loc_block_len;
2802
2
    attr->srv6_l3vpn->loc_node_len = loc_node_len;
2803
2
    attr->srv6_l3vpn->func_len = func_len;
2804
2
    attr->srv6_l3vpn->arg_len = arg_len;
2805
2
    attr->srv6_l3vpn->transposition_len = transposition_len;
2806
2
    attr->srv6_l3vpn->transposition_offset = transposition_offset;
2807
2
  }
2808
2809
2
  else {
2810
2
    if (bgp_debug_update(peer, NULL, NULL, 1))
2811
0
      zlog_debug(
2812
2
        "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2813
2
        peer->host, type);
2814
2815
2
    stream_forward_getp(peer->curr, length);
2816
2
  }
2817
2818
4
  return BGP_ATTR_PARSE_PROCEED;
2819
4
}
2820
2821
/* SRv6 Service Sub-TLV attribute
2822
 * draft-ietf-bess-srv6-services-07
2823
 */
2824
static enum bgp_attr_parse_ret
2825
bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
2826
17
{
2827
17
  struct peer *const peer = args->peer;
2828
17
  struct attr *const attr = args->attr;
2829
17
  struct in6_addr ipv6_sid;
2830
17
  uint8_t type, sid_flags;
2831
17
  uint16_t length, endpoint_behavior;
2832
17
  size_t headersz = sizeof(type) + sizeof(length);
2833
17
  enum bgp_attr_parse_ret err;
2834
2835
17
  if (STREAM_READABLE(peer->curr) < headersz) {
2836
0
    flog_err(
2837
0
      EC_BGP_ATTR_LEN,
2838
0
      "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2839
0
      headersz, STREAM_READABLE(peer->curr));
2840
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2841
0
            args->total);
2842
0
  }
2843
2844
17
  type = stream_getc(peer->curr);
2845
17
  length = stream_getw(peer->curr);
2846
2847
17
  if (STREAM_READABLE(peer->curr) < length) {
2848
2
    flog_err(
2849
2
      EC_BGP_ATTR_LEN,
2850
2
      "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2851
2
      length, STREAM_READABLE(peer->curr));
2852
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2853
2
            args->total);
2854
2
  }
2855
2856
15
  if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
2857
10
    if (STREAM_READABLE(peer->curr) <
2858
10
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2859
0
      flog_err(
2860
0
        EC_BGP_ATTR_LEN,
2861
0
        "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2862
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
2863
0
        STREAM_READABLE(peer->curr));
2864
0
      return bgp_attr_malformed(
2865
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2866
0
        args->total);
2867
0
    }
2868
10
    stream_getc(peer->curr);
2869
10
    stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2870
10
    sid_flags = stream_getc(peer->curr);
2871
10
    endpoint_behavior = stream_getw(peer->curr);
2872
10
    stream_getc(peer->curr);
2873
2874
    /* Log SRv6 Service Sub-TLV */
2875
10
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
2876
0
      zlog_debug(
2877
10
        "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2878
10
        __func__, &ipv6_sid, sid_flags,
2879
10
        endpoint_behavior);
2880
2881
    /* Configure from Info */
2882
10
    if (attr->srv6_l3vpn) {
2883
1
      flog_err(EC_BGP_ATTRIBUTE_REPEATED,
2884
1
         "Prefix SID SRv6 L3VPN field repeated");
2885
1
      return bgp_attr_malformed(
2886
1
        args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
2887
1
    }
2888
9
    attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2889
9
             sizeof(struct bgp_attr_srv6_l3vpn));
2890
9
    sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
2891
9
    attr->srv6_l3vpn->sid_flags = sid_flags;
2892
9
    attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
2893
9
    attr->srv6_l3vpn->loc_block_len = 0;
2894
9
    attr->srv6_l3vpn->loc_node_len = 0;
2895
9
    attr->srv6_l3vpn->func_len = 0;
2896
9
    attr->srv6_l3vpn->arg_len = 0;
2897
9
    attr->srv6_l3vpn->transposition_len = 0;
2898
9
    attr->srv6_l3vpn->transposition_offset = 0;
2899
2900
    // Sub-Sub-TLV found
2901
9
    if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2902
7
      err = bgp_attr_srv6_service_data(args);
2903
2904
7
      if (err != BGP_ATTR_PARSE_PROCEED)
2905
3
        return err;
2906
7
    }
2907
2908
6
    attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
2909
6
  }
2910
2911
  /* Placeholder code for unsupported type */
2912
5
  else {
2913
5
    if (bgp_debug_update(peer, NULL, NULL, 1))
2914
0
      zlog_debug(
2915
5
        "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2916
5
        peer->host, type);
2917
2918
5
    stream_forward_getp(peer->curr, length);
2919
5
  }
2920
2921
11
  return BGP_ATTR_PARSE_PROCEED;
2922
15
}
2923
2924
/*
2925
 * Read an individual SID value returning how much data we have read
2926
 * Returns 0 if there was an error that needs to be passed up the stack
2927
 */
2928
static enum bgp_attr_parse_ret
2929
bgp_attr_psid_sub(uint8_t type, uint16_t length,
2930
      struct bgp_attr_parser_args *args)
2931
231
{
2932
231
  struct peer *const peer = args->peer;
2933
231
  struct attr *const attr = args->attr;
2934
231
  uint32_t label_index;
2935
231
  struct in6_addr ipv6_sid;
2936
231
  uint32_t srgb_base;
2937
231
  uint32_t srgb_range;
2938
231
  int srgb_count;
2939
231
  uint8_t sid_type, sid_flags;
2940
2941
  /*
2942
   * Check that we actually have at least as much data as
2943
   * specified by the length field
2944
   */
2945
231
  if (STREAM_READABLE(peer->curr) < length) {
2946
0
    flog_err(
2947
0
      EC_BGP_ATTR_LEN,
2948
0
      "Prefix SID specifies length %hu, but only %zu bytes remain",
2949
0
      length, STREAM_READABLE(peer->curr));
2950
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2951
0
            args->total);
2952
0
  }
2953
2954
231
  if (type == BGP_PREFIX_SID_LABEL_INDEX) {
2955
3
    if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
2956
2
      flog_err(EC_BGP_ATTR_LEN,
2957
2
         "Prefix SID label index length is %hu instead of %u",
2958
2
         length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
2959
2
      return bgp_attr_malformed(args,
2960
2
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2961
2
              args->total);
2962
2
    }
2963
2964
    /* Ignore flags and reserved */
2965
1
    stream_getc(peer->curr);
2966
1
    stream_getw(peer->curr);
2967
2968
    /* Fetch the label index and see if it is valid. */
2969
1
    label_index = stream_getl(peer->curr);
2970
1
    if (label_index == BGP_INVALID_LABEL_INDEX)
2971
0
      return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2972
0
              args->total);
2973
2974
    /* Store label index; subsequently, we'll check on
2975
     * address-family */
2976
1
    attr->label_index = label_index;
2977
228
  } else if (type == BGP_PREFIX_SID_IPV6) {
2978
0
    if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
2979
0
      flog_err(EC_BGP_ATTR_LEN,
2980
0
         "Prefix SID IPv6 length is %hu instead of %u",
2981
0
         length, BGP_PREFIX_SID_IPV6_LENGTH);
2982
0
      return bgp_attr_malformed(args,
2983
0
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2984
0
              args->total);
2985
0
    }
2986
2987
    /* Ignore reserved */
2988
0
    stream_getc(peer->curr);
2989
0
    stream_getw(peer->curr);
2990
2991
0
    stream_get(&ipv6_sid, peer->curr, 16);
2992
228
  } else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
2993
    /*
2994
     * ietf-idr-bgp-prefix-sid-05:
2995
     *     Length is the total length of the value portion of the
2996
     *     TLV: 2 + multiple of 6.
2997
     *
2998
     * peer->curr stream readp should be at the beginning of the 16
2999
     * bit flag field at this point in the code.
3000
     */
3001
3002
    /*
3003
     * Check that the TLV length field is sane: at least 2 bytes of
3004
     * flag, and at least 1 SRGB (these are 6 bytes each)
3005
     */
3006
4
    if (length < (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)) {
3007
0
      flog_err(
3008
0
        EC_BGP_ATTR_LEN,
3009
0
        "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
3010
0
        length,
3011
0
        2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3012
0
      return bgp_attr_malformed(
3013
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3014
0
        args->total);
3015
0
    }
3016
3017
    /*
3018
     * Check that the portion of the TLV containing the sequence of
3019
     * SRGBs corresponds to a multiple of the SRGB size; to get
3020
     * that length, we skip the 16 bit flags field
3021
     */
3022
4
    stream_getw(peer->curr);
3023
4
    length -= 2;
3024
4
    if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
3025
2
      flog_err(
3026
2
        EC_BGP_ATTR_LEN,
3027
2
        "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
3028
2
        length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3029
2
      return bgp_attr_malformed(
3030
2
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3031
2
        args->total);
3032
2
    }
3033
3034
2
    srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
3035
3036
197
    for (int i = 0; i < srgb_count; i++) {
3037
195
      stream_get(&srgb_base, peer->curr, 3);
3038
195
      stream_get(&srgb_range, peer->curr, 3);
3039
195
    }
3040
224
  } else if (type == BGP_PREFIX_SID_VPN_SID) {
3041
2
    if (length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
3042
2
      flog_err(EC_BGP_ATTR_LEN,
3043
2
         "Prefix SID VPN SID length is %hu instead of %u",
3044
2
         length, BGP_PREFIX_SID_VPN_SID_LENGTH);
3045
2
      return bgp_attr_malformed(args,
3046
2
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3047
2
              args->total);
3048
2
    }
3049
3050
    /* Parse VPN-SID Sub-TLV */
3051
0
    stream_getc(peer->curr);               /* reserved  */
3052
0
    sid_type = stream_getc(peer->curr);    /* sid_type  */
3053
0
    sid_flags = stream_getc(peer->curr);   /* sid_flags */
3054
0
    stream_get(&ipv6_sid, peer->curr,
3055
0
         sizeof(ipv6_sid)); /* sid_value */
3056
3057
    /* Log VPN-SID Sub-TLV */
3058
0
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
3059
0
      zlog_debug(
3060
0
        "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3061
0
        __func__, &ipv6_sid, sid_type, sid_flags);
3062
3063
    /* Configure from Info */
3064
0
    if (attr->srv6_vpn) {
3065
0
      flog_err(EC_BGP_ATTRIBUTE_REPEATED,
3066
0
         "Prefix SID SRv6 VPN field repeated");
3067
0
      return bgp_attr_malformed(
3068
0
        args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
3069
0
    }
3070
0
    attr->srv6_vpn = XCALLOC(MTYPE_BGP_SRV6_VPN,
3071
0
           sizeof(struct bgp_attr_srv6_vpn));
3072
0
    attr->srv6_vpn->sid_flags = sid_flags;
3073
0
    sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
3074
0
    attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
3075
222
  } else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
3076
20
    if (STREAM_READABLE(peer->curr) < 1) {
3077
3
      flog_err(
3078
3
        EC_BGP_ATTR_LEN,
3079
3
        "Prefix SID SRV6 L3 Service not enough data left, it must be at least 1 byte");
3080
3
      return bgp_attr_malformed(
3081
3
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3082
3
        args->total);
3083
3
    }
3084
    /* ignore reserved */
3085
17
    stream_getc(peer->curr);
3086
3087
17
    return bgp_attr_srv6_service(args);
3088
20
  }
3089
  /* Placeholder code for Unsupported TLV */
3090
202
  else {
3091
202
    if (bgp_debug_update(peer, NULL, NULL, 1))
3092
0
      zlog_debug(
3093
202
        "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3094
202
        peer->host, type);
3095
3096
202
    stream_forward_getp(peer->curr, length);
3097
202
  }
3098
3099
205
  return BGP_ATTR_PARSE_PROCEED;
3100
231
}
3101
3102
/* Prefix SID attribute
3103
 * draft-ietf-idr-bgp-prefix-sid-05
3104
 */
3105
enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
3106
35
{
3107
35
  struct peer *const peer = args->peer;
3108
35
  struct attr *const attr = args->attr;
3109
35
  enum bgp_attr_parse_ret ret;
3110
3111
35
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3112
3113
35
  uint8_t type;
3114
35
  uint16_t length;
3115
35
  size_t headersz = sizeof(type) + sizeof(length);
3116
35
  size_t psid_parsed_length = 0;
3117
3118
248
  while (STREAM_READABLE(peer->curr) > 0
3119
248
         && psid_parsed_length < args->length) {
3120
3121
246
    if (STREAM_READABLE(peer->curr) < headersz) {
3122
1
      flog_err(
3123
1
        EC_BGP_ATTR_LEN,
3124
1
        "Malformed Prefix SID attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
3125
1
        headersz, STREAM_READABLE(peer->curr));
3126
1
      return bgp_attr_malformed(
3127
1
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3128
1
        args->total);
3129
1
    }
3130
3131
245
    type = stream_getc(peer->curr);
3132
245
    length = stream_getw(peer->curr);
3133
3134
245
    if (STREAM_READABLE(peer->curr) < length) {
3135
14
      flog_err(
3136
14
        EC_BGP_ATTR_LEN,
3137
14
        "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3138
14
        length, STREAM_READABLE(peer->curr));
3139
14
      return bgp_attr_malformed(args,
3140
14
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3141
14
              args->total);
3142
14
    }
3143
3144
231
    ret = bgp_attr_psid_sub(type, length, args);
3145
3146
231
    if (ret != BGP_ATTR_PARSE_PROCEED)
3147
15
      return ret;
3148
3149
216
    psid_parsed_length += length + headersz;
3150
3151
216
    if (psid_parsed_length > args->length) {
3152
3
      flog_err(
3153
3
        EC_BGP_ATTR_LEN,
3154
3
        "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu for TLV length, have %zu overflowed in UPDATE)",
3155
3
        length + headersz, psid_parsed_length - (length + headersz));
3156
3
      return bgp_attr_malformed(
3157
3
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3158
3
        args->total);
3159
3
    }
3160
216
  }
3161
3162
2
  return BGP_ATTR_PARSE_PROCEED;
3163
35
}
3164
3165
/* PMSI tunnel attribute (RFC 6514)
3166
 * Basic validation checks done here.
3167
 */
3168
static enum bgp_attr_parse_ret
3169
bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
3170
1
{
3171
1
  struct peer *const peer = args->peer;
3172
1
  struct attr *const attr = args->attr;
3173
1
  const bgp_size_t length = args->length;
3174
1
  uint8_t tnl_type;
3175
1
  int attr_parse_len = 2 + BGP_LABEL_BYTES;
3176
3177
  /* Verify that the receiver is expecting "ingress replication" as we
3178
   * can only support that.
3179
   */
3180
1
  if (length < attr_parse_len) {
3181
0
    flog_err(EC_BGP_ATTR_LEN, "Bad PMSI tunnel attribute length %d",
3182
0
       length);
3183
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3184
0
            args->total);
3185
0
  }
3186
1
  stream_getc(peer->curr); /* Flags */
3187
1
  tnl_type = stream_getc(peer->curr);
3188
1
  if (tnl_type > PMSI_TNLTYPE_MAX) {
3189
1
    flog_err(EC_BGP_ATTR_PMSI_TYPE,
3190
1
       "Invalid PMSI tunnel attribute type %d", tnl_type);
3191
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
3192
1
            args->total);
3193
1
  }
3194
0
  if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
3195
0
    if (length != 9) {
3196
0
      flog_err(EC_BGP_ATTR_PMSI_LEN,
3197
0
         "Bad PMSI tunnel attribute length %d for IR",
3198
0
         length);
3199
0
      return bgp_attr_malformed(
3200
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3201
0
        args->total);
3202
0
    }
3203
0
  }
3204
3205
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
3206
0
  bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
3207
0
  stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
3208
3209
  /* Forward read pointer of input stream. */
3210
0
  stream_forward_getp(peer->curr, length - attr_parse_len);
3211
3212
0
  return BGP_ATTR_PARSE_PROCEED;
3213
0
}
3214
3215
/* AIGP attribute (rfc7311) */
3216
static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
3217
2
{
3218
2
  struct peer *const peer = args->peer;
3219
2
  struct attr *const attr = args->attr;
3220
2
  const bgp_size_t length = args->length;
3221
2
  uint8_t *s = stream_pnt(peer->curr);
3222
2
  uint64_t aigp = 0;
3223
3224
  /* If an AIGP attribute is received on a BGP session for which
3225
   * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3226
   * as if it were an unrecognized non-transitive attribute.
3227
   * That is, it "MUST be quietly ignored and not passed along to
3228
   * other BGP peers".
3229
   * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3230
   * sessions between members of the same BGP Confederation,
3231
   * the default value of AIGP_SESSION SHOULD be "enabled".
3232
   */
3233
2
  if (peer->sort == BGP_PEER_EBGP &&
3234
2
      !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
3235
2
    zlog_warn(
3236
2
      "%pBP received AIGP attribute, but eBGP peer do not support it",
3237
2
      peer);
3238
2
    goto aigp_ignore;
3239
2
  }
3240
3241
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
3242
0
    goto aigp_ignore;
3243
3244
0
  if (!bgp_attr_aigp_valid(s, length))
3245
0
    goto aigp_ignore;
3246
3247
  /* Extract AIGP Metric TLV */
3248
0
  if (bgp_attr_aigp_get_tlv_metric(s, length, &aigp))
3249
0
    bgp_attr_set_aigp_metric(attr, aigp);
3250
3251
2
aigp_ignore:
3252
2
  stream_forward_getp(peer->curr, length);
3253
3254
2
  return bgp_attr_ignore(peer, args->type);
3255
0
}
3256
3257
/* OTC attribute. */
3258
static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
3259
0
{
3260
0
  struct peer *const peer = args->peer;
3261
0
  struct attr *const attr = args->attr;
3262
0
  const bgp_size_t length = args->length;
3263
3264
  /* Length check. */
3265
0
  if (length != 4) {
3266
0
    flog_err(EC_BGP_ATTR_LEN, "OTC attribute length isn't 4 [%u]",
3267
0
       length);
3268
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3269
0
            args->total);
3270
0
  }
3271
3272
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
3273
0
    goto otc_ignore;
3274
3275
0
  attr->otc = stream_getl(peer->curr);
3276
0
  if (!attr->otc) {
3277
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH, "OTC attribute value is 0");
3278
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
3279
0
            args->total);
3280
0
  }
3281
3282
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
3283
3284
0
  return BGP_ATTR_PARSE_PROCEED;
3285
3286
0
otc_ignore:
3287
0
  stream_forward_getp(peer->curr, length);
3288
3289
0
  return bgp_attr_ignore(peer, args->type);
3290
0
}
3291
3292
/* BGP unknown attribute treatment. */
3293
static enum bgp_attr_parse_ret
3294
bgp_attr_unknown(struct bgp_attr_parser_args *args)
3295
451
{
3296
451
  bgp_size_t total = args->total;
3297
451
  struct transit *transit;
3298
451
  struct peer *const peer = args->peer;
3299
451
  struct attr *const attr = args->attr;
3300
451
  uint8_t *const startp = args->startp;
3301
451
  const uint8_t type = args->type;
3302
451
  const uint8_t flag = args->flags;
3303
451
  const bgp_size_t length = args->length;
3304
3305
451
  if (bgp_debug_update(peer, NULL, NULL, 1))
3306
0
    zlog_debug(
3307
451
      "%s Unknown attribute is received (type %d, length %d)",
3308
451
      peer->host, type, length);
3309
3310
  /* Forward read pointer of input stream. */
3311
451
  stream_forward_getp(peer->curr, length);
3312
3313
451
  if (peer->discard_attrs[type] || peer->withdraw_attrs[type])
3314
0
    return bgp_attr_ignore(peer, type);
3315
3316
  /* If any of the mandatory well-known attributes are not recognized,
3317
     then the Error Subcode is set to Unrecognized Well-known
3318
     Attribute.  The Data field contains the unrecognized attribute
3319
     (type, length and value). */
3320
451
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
3321
32
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR,
3322
32
            args->total);
3323
32
  }
3324
3325
  /* Unrecognized non-transitive optional attributes must be quietly
3326
     ignored and not passed along to other BGP peers. */
3327
419
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3328
255
    return BGP_ATTR_PARSE_PROCEED;
3329
3330
  /* If a path with recognized transitive optional attribute is
3331
     accepted and passed along to other BGP peers and the Partial bit
3332
     in the Attribute Flags octet is set to 1 by some previous AS, it
3333
     is not set back to 0 by the current AS. */
3334
164
  SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3335
3336
  /* Store transitive attribute to the end of attr->transit. */
3337
164
  transit = bgp_attr_get_transit(attr);
3338
164
  if (!transit)
3339
141
    transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
3340
3341
164
  transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3342
164
        transit->length + total);
3343
3344
164
  memcpy(transit->val + transit->length, startp, total);
3345
164
  transit->length += total;
3346
164
  bgp_attr_set_transit(attr, transit);
3347
3348
164
  return BGP_ATTR_PARSE_PROCEED;
3349
419
}
3350
3351
/* Well-known attribute check. */
3352
static int bgp_attr_check(struct peer *peer, struct attr *attr)
3353
302
{
3354
302
  uint8_t type = 0;
3355
3356
  /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3357
   * empty UPDATE.  */
3358
302
  if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag)
3359
0
    return BGP_ATTR_PARSE_PROCEED;
3360
3361
  /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required
3362
     to carry any other path attributes.", though if MP_REACH_NLRI or NLRI
3363
     are present, it should.  Check for any other attribute being present
3364
     instead.
3365
   */
3366
302
  if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3367
35
       CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
3368
6
    return BGP_ATTR_PARSE_PROCEED;
3369
3370
296
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3371
37
    type = BGP_ATTR_ORIGIN;
3372
3373
296
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3374
37
    type = BGP_ATTR_AS_PATH;
3375
3376
  /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3377
   * and
3378
   * NLRI is empty. We can't easily check NLRI empty here though.
3379
   */
3380
296
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3381
296
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3382
29
    type = BGP_ATTR_NEXT_HOP;
3383
3384
296
  if (peer->sort == BGP_PEER_IBGP
3385
0
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
3386
0
    type = BGP_ATTR_LOCAL_PREF;
3387
3388
  /* If any of the well-known mandatory attributes are not present
3389
   * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3390
   */
3391
296
  if (type) {
3392
37
    flog_warn(EC_BGP_MISSING_ATTRIBUTE,
3393
37
        "%s Missing well-known attribute %s.", peer->host,
3394
37
        lookup_msg(attr_str, type, NULL));
3395
37
    return BGP_ATTR_PARSE_WITHDRAW;
3396
37
  }
3397
259
  return BGP_ATTR_PARSE_PROCEED;
3398
296
}
3399
3400
/* Read attribute of update packet.  This function is called from
3401
   bgp_update_receive() in bgp_packet.c.  */
3402
enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
3403
               bgp_size_t size,
3404
               struct bgp_nlri *mp_update,
3405
               struct bgp_nlri *mp_withdraw)
3406
602
{
3407
602
  enum bgp_attr_parse_ret ret;
3408
602
  uint8_t flag = 0;
3409
602
  uint8_t type = 0;
3410
602
  bgp_size_t length;
3411
602
  uint8_t *startp, *endp;
3412
602
  uint8_t *attr_endp;
3413
602
  uint8_t seen[BGP_ATTR_BITMAP_SIZE];
3414
  /* we need the as4_path only until we have synthesized the as_path with
3415
   * it */
3416
  /* same goes for as4_aggregator */
3417
602
  struct aspath *as4_path = NULL;
3418
602
  as_t as4_aggregator = 0;
3419
602
  struct in_addr as4_aggregator_addr = {.s_addr = 0};
3420
602
  struct transit *transit;
3421
3422
  /* Initialize bitmap. */
3423
602
  memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3424
3425
  /* End pointer of BGP attribute. */
3426
602
  endp = BGP_INPUT_PNT(peer) + size;
3427
3428
  /* Get attributes to the end of attribute length. */
3429
2.16k
  while (BGP_INPUT_PNT(peer) < endp) {
3430
    /* Check remaining length check.*/
3431
1.86k
    if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
3432
      /* XXX warning: long int format, int arg (arg 5) */
3433
6
      flog_warn(
3434
6
        EC_BGP_ATTRIBUTE_TOO_SMALL,
3435
6
        "%s: error BGP attribute length %lu is smaller than min len",
3436
6
        peer->host,
3437
6
        (unsigned long)(endp
3438
6
            - stream_pnt(BGP_INPUT(peer))));
3439
3440
6
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3441
6
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3442
6
      ret = BGP_ATTR_PARSE_ERROR;
3443
6
      goto done;
3444
6
    }
3445
3446
    /* Fetch attribute flag and type. */
3447
1.85k
    startp = BGP_INPUT_PNT(peer);
3448
    /* "The lower-order four bits of the Attribute Flags octet are
3449
       unused.  They MUST be zero when sent and MUST be ignored when
3450
       received." */
3451
1.85k
    flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3452
1.85k
    type = stream_getc(BGP_INPUT(peer));
3453
3454
    /* Check whether Extended-Length applies and is in bounds */
3455
1.85k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3456
432
        && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
3457
1
      flog_warn(
3458
1
        EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
3459
1
        "%s: Extended length set, but just %lu bytes of attr header",
3460
1
        peer->host,
3461
1
        (unsigned long)(endp
3462
1
            - stream_pnt(BGP_INPUT(peer))));
3463
3464
1
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3465
1
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3466
1
      ret = BGP_ATTR_PARSE_ERROR;
3467
1
      goto done;
3468
1
    }
3469
3470
    /* Check extended attribue length bit. */
3471
1.85k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3472
431
      length = stream_getw(BGP_INPUT(peer));
3473
1.42k
    else
3474
1.42k
      length = stream_getc(BGP_INPUT(peer));
3475
3476
    /* If any attribute appears more than once in the UPDATE
3477
       message, then the Error Subcode is set to Malformed Attribute
3478
       List. */
3479
3480
1.85k
    if (CHECK_BITMAP(seen, type)) {
3481
9
      flog_warn(
3482
9
        EC_BGP_ATTRIBUTE_REPEATED,
3483
9
        "%s: error BGP attribute type %d appears twice in a message",
3484
9
        peer->host, type);
3485
3486
9
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3487
9
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3488
9
      ret = BGP_ATTR_PARSE_ERROR;
3489
9
      goto done;
3490
9
    }
3491
3492
    /* Set type to bitmap to check duplicate attribute.  `type' is
3493
       unsigned char so it never overflow bitmap range. */
3494
3495
1.84k
    SET_BITMAP(seen, type);
3496
3497
    /* Overflow check. */
3498
1.84k
    attr_endp = BGP_INPUT_PNT(peer) + length;
3499
3500
1.84k
    if (attr_endp > endp) {
3501
106
      flog_warn(
3502
106
        EC_BGP_ATTRIBUTE_TOO_LARGE,
3503
106
        "%s: BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p",
3504
106
        peer->host, type, length, size, attr_endp,
3505
106
        endp);
3506
      /*
3507
       * RFC 4271 6.3
3508
       * If any recognized attribute has an Attribute
3509
       * Length that conflicts with the expected length
3510
       * (based on the attribute type code), then the
3511
       * Error Subcode MUST be set to Attribute Length
3512
       * Error.  The Data field MUST contain the erroneous
3513
       * attribute (type, length, and value).
3514
       * ----------
3515
       * We do not currently have a good way to determine the
3516
       * length of the attribute independent of the length
3517
       * received in the message. Instead we send the
3518
       * minimum between the amount of data we have and the
3519
       * amount specified by the attribute length field.
3520
       *
3521
       * Instead of directly passing in the packet buffer and
3522
       * offset we use the stream_get* functions to read into
3523
       * a stack buffer, since they perform bounds checking
3524
       * and we are working with untrusted data.
3525
       */
3526
106
      unsigned char ndata[peer->max_packet_size];
3527
106
      memset(ndata, 0x00, sizeof(ndata));
3528
106
      size_t lfl =
3529
106
        CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3530
      /* Rewind to end of flag field */
3531
106
      stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
3532
      /* Type */
3533
106
      stream_get(&ndata[0], BGP_INPUT(peer), 1);
3534
      /* Length */
3535
106
      stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3536
      /* Value */
3537
106
      size_t atl = attr_endp - startp;
3538
106
      size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3539
106
      stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3540
3541
106
      bgp_notify_send_with_data(
3542
106
        peer, BGP_NOTIFY_UPDATE_ERR,
3543
106
        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3544
106
        ndl + lfl + 1);
3545
3546
106
      ret = BGP_ATTR_PARSE_ERROR;
3547
106
      goto done;
3548
106
    }
3549
3550
1.74k
    struct bgp_attr_parser_args attr_args = {
3551
1.74k
      .peer = peer,
3552
1.74k
      .length = length,
3553
1.74k
      .attr = attr,
3554
1.74k
      .type = type,
3555
1.74k
      .flags = flag,
3556
1.74k
      .startp = startp,
3557
1.74k
      .total = attr_endp - startp,
3558
1.74k
    };
3559
3560
3561
    /* If any recognized attribute has Attribute Flags that conflict
3562
       with the Attribute Type Code, then the Error Subcode is set
3563
       to
3564
       Attribute Flags Error.  The Data field contains the erroneous
3565
       attribute (type, length and value). */
3566
1.74k
    if (bgp_attr_flag_invalid(&attr_args)) {
3567
43
      ret = bgp_attr_malformed(
3568
43
        &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3569
43
        attr_args.total);
3570
43
      if (ret == BGP_ATTR_PARSE_PROCEED)
3571
13
        continue;
3572
30
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3573
30
      goto done;
3574
43
    }
3575
3576
    /* OK check attribute and store it's value. */
3577
1.69k
    switch (type) {
3578
262
    case BGP_ATTR_ORIGIN:
3579
262
      ret = bgp_attr_origin(&attr_args);
3580
262
      break;
3581
277
    case BGP_ATTR_AS_PATH:
3582
277
      ret = bgp_attr_aspath(&attr_args);
3583
277
      break;
3584
41
    case BGP_ATTR_AS4_PATH:
3585
41
      ret = bgp_attr_as4_path(&attr_args, &as4_path);
3586
41
      break;
3587
64
    case BGP_ATTR_NEXT_HOP:
3588
64
      ret = bgp_attr_nexthop(&attr_args);
3589
64
      break;
3590
7
    case BGP_ATTR_MULTI_EXIT_DISC:
3591
7
      ret = bgp_attr_med(&attr_args);
3592
7
      break;
3593
3
    case BGP_ATTR_LOCAL_PREF:
3594
3
      ret = bgp_attr_local_pref(&attr_args);
3595
3
      break;
3596
7
    case BGP_ATTR_ATOMIC_AGGREGATE:
3597
7
      ret = bgp_attr_atomic(&attr_args);
3598
7
      break;
3599
2
    case BGP_ATTR_AGGREGATOR:
3600
2
      ret = bgp_attr_aggregator(&attr_args);
3601
2
      break;
3602
2
    case BGP_ATTR_AS4_AGGREGATOR:
3603
2
      ret = bgp_attr_as4_aggregator(&attr_args,
3604
2
                  &as4_aggregator,
3605
2
                  &as4_aggregator_addr);
3606
2
      break;
3607
25
    case BGP_ATTR_COMMUNITIES:
3608
25
      ret = bgp_attr_community(&attr_args);
3609
25
      break;
3610
12
    case BGP_ATTR_LARGE_COMMUNITIES:
3611
12
      ret = bgp_attr_large_community(&attr_args);
3612
12
      break;
3613
8
    case BGP_ATTR_ORIGINATOR_ID:
3614
8
      ret = bgp_attr_originator_id(&attr_args);
3615
8
      break;
3616
20
    case BGP_ATTR_CLUSTER_LIST:
3617
20
      ret = bgp_attr_cluster_list(&attr_args);
3618
20
      break;
3619
323
    case BGP_ATTR_MP_REACH_NLRI:
3620
323
      ret = bgp_mp_reach_parse(&attr_args, mp_update);
3621
323
      break;
3622
12
    case BGP_ATTR_MP_UNREACH_NLRI:
3623
12
      ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3624
12
      break;
3625
110
    case BGP_ATTR_EXT_COMMUNITIES:
3626
110
      ret = bgp_attr_ext_communities(&attr_args);
3627
110
      break;
3628
#ifdef ENABLE_BGP_VNC_ATTR
3629
    case BGP_ATTR_VNC:
3630
#endif
3631
6
    case BGP_ATTR_ENCAP:
3632
6
      ret = bgp_attr_encap(&attr_args);
3633
6
      break;
3634
35
    case BGP_ATTR_PREFIX_SID:
3635
35
      ret = bgp_attr_prefix_sid(&attr_args);
3636
35
      break;
3637
1
    case BGP_ATTR_PMSI_TUNNEL:
3638
1
      ret = bgp_attr_pmsi_tunnel(&attr_args);
3639
1
      break;
3640
29
    case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3641
29
      ret = bgp_attr_ipv6_ext_communities(&attr_args);
3642
29
      break;
3643
0
    case BGP_ATTR_OTC:
3644
0
      ret = bgp_attr_otc(&attr_args);
3645
0
      break;
3646
2
    case BGP_ATTR_AIGP:
3647
2
      ret = bgp_attr_aigp(&attr_args);
3648
2
      break;
3649
451
    default:
3650
451
      ret = bgp_attr_unknown(&attr_args);
3651
451
      break;
3652
1.69k
    }
3653
3654
1.69k
    if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3655
54
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3656
54
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3657
54
      ret = BGP_ATTR_PARSE_ERROR;
3658
54
      goto done;
3659
54
    }
3660
3661
1.64k
    if (ret == BGP_ATTR_PARSE_EOR) {
3662
39
      goto done;
3663
39
    }
3664
3665
1.60k
    if (ret == BGP_ATTR_PARSE_ERROR) {
3666
2
      flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
3667
2
          "%s: Attribute %s, parse error", peer->host,
3668
2
          lookup_msg(attr_str, type, NULL));
3669
2
      goto done;
3670
2
    }
3671
1.60k
    if (ret == BGP_ATTR_PARSE_WITHDRAW) {
3672
53
      flog_warn(
3673
53
        EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
3674
53
        "%s: Attribute %s, parse error - treating as withdrawal",
3675
53
        peer->host, lookup_msg(attr_str, type, NULL));
3676
53
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3677
53
      goto done;
3678
53
    }
3679
3680
    /* Check the fetched length. */
3681
1.55k
    if (BGP_INPUT_PNT(peer) != attr_endp) {
3682
0
      flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
3683
0
          "%s: BGP attribute %s, fetch error",
3684
0
          peer->host, lookup_msg(attr_str, type, NULL));
3685
0
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3686
0
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3687
0
      ret = BGP_ATTR_PARSE_ERROR;
3688
0
      goto done;
3689
0
    }
3690
1.55k
  }
3691
3692
  /*
3693
   * draft-ietf-idr-bgp-prefix-sid-27#section-3:
3694
   * About Prefix-SID path attribute,
3695
   * Label-Index TLV(type1) and The Originator SRGB TLV(type-3)
3696
   * may only appear in a BGP Prefix-SID attribute attached to
3697
   * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]).
3698
   * It MUST be ignored when received for other BGP AFI/SAFI combinations.
3699
   */
3700
302
  if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3701
302
    attr->label_index = BGP_INVALID_LABEL_INDEX;
3702
3703
  /* Check final read pointer is same as end pointer. */
3704
302
  if (BGP_INPUT_PNT(peer) != endp) {
3705
0
    flog_warn(EC_BGP_ATTRIBUTES_MISMATCH,
3706
0
        "%s: BGP attribute %s, length mismatch", peer->host,
3707
0
        lookup_msg(attr_str, type, NULL));
3708
0
    bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3709
0
        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3710
3711
0
    ret = BGP_ATTR_PARSE_ERROR;
3712
0
    goto done;
3713
0
  }
3714
3715
  /*
3716
   * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
3717
   * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
3718
   * This is implemented below and will result in a NOTIFICATION. If the
3719
   * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
3720
   * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
3721
   * message SHOULD NOT be sent. This is implemented elsewhere.
3722
   *
3723
   * RFC4760: An UPDATE message that carries no NLRI, other than the one
3724
   * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
3725
   * attribute. If such a message contains the NEXT_HOP attribute, the BGP
3726
   * speaker that receives the message SHOULD ignore this attribute.
3727
   */
3728
302
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3729
0
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
3730
0
    if (bgp_attr_nexthop_valid(peer, attr) < 0) {
3731
0
      ret = BGP_ATTR_PARSE_ERROR;
3732
0
      goto done;
3733
0
    }
3734
0
  }
3735
3736
  /* Check all mandatory well-known attributes are present */
3737
302
  ret = bgp_attr_check(peer, attr);
3738
302
  if (ret < 0)
3739
37
    goto done;
3740
3741
  /*
3742
   * At this place we can see whether we got AS4_PATH and/or
3743
   * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3744
   * We can not do this before we've read all attributes because
3745
   * the as4 handling does not say whether AS4_PATH has to be sent
3746
   * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3747
   * in relationship to AGGREGATOR.
3748
   * So, to be defensive, we are not relying on any order and read
3749
   * all attributes first, including these 32bit ones, and now,
3750
   * afterwards, we look what and if something is to be done for as4.
3751
   *
3752
   * It is possible to not have AS_PATH, e.g. GR EoR and sole
3753
   * MP_UNREACH_NLRI.
3754
   */
3755
  /* actually... this doesn't ever return failure currently, but
3756
   * better safe than sorry */
3757
265
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3758
259
      && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3759
259
          &as4_aggregator_addr)) {
3760
0
    bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3761
0
        BGP_NOTIFY_UPDATE_MAL_ATTR);
3762
0
    ret = BGP_ATTR_PARSE_ERROR;
3763
0
    goto done;
3764
0
  }
3765
3766
  /*
3767
   * Finally do the checks on the aspath we did not do yet
3768
   * because we waited for a potentially synthesized aspath.
3769
   */
3770
265
  if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3771
259
    ret = bgp_attr_aspath_check(peer, attr);
3772
259
    if (ret != BGP_ATTR_PARSE_PROCEED)
3773
1
      goto done;
3774
259
  }
3775
3776
264
  ret = BGP_ATTR_PARSE_PROCEED;
3777
602
done:
3778
3779
  /*
3780
   * At this stage, we have done all fiddling with as4, and the
3781
   * resulting info is in attr->aggregator resp. attr->aspath so
3782
   * we can chuck as4_aggregator and as4_path alltogether in order
3783
   * to save memory
3784
   */
3785
  /*
3786
   * unintern - it is in the hash
3787
   * The flag that we got this is still there, but that
3788
   * does not do any trouble
3789
   */
3790
602
  aspath_unintern(&as4_path);
3791
3792
602
  transit = bgp_attr_get_transit(attr);
3793
602
  if (ret != BGP_ATTR_PARSE_ERROR) {
3794
    /* Finally intern unknown attribute. */
3795
424
    if (transit)
3796
128
      bgp_attr_set_transit(attr, transit_intern(transit));
3797
424
    if (attr->encap_subtlvs)
3798
5
      attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3799
5
                 ENCAP_SUBTLV_TYPE);
3800
424
#ifdef ENABLE_BGP_VNC
3801
424
    struct bgp_attr_encap_subtlv *vnc_subtlvs =
3802
424
      bgp_attr_get_vnc_subtlvs(attr);
3803
3804
424
    if (vnc_subtlvs)
3805
0
      bgp_attr_set_vnc_subtlvs(
3806
0
        attr,
3807
0
        encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
3808
424
#endif
3809
424
  } else {
3810
178
    if (transit) {
3811
13
      transit_free(transit);
3812
13
      bgp_attr_set_transit(attr, NULL);
3813
13
    }
3814
3815
178
    bgp_attr_flush_encap(attr);
3816
178
  };
3817
3818
  /* Sanity checks */
3819
602
  transit = bgp_attr_get_transit(attr);
3820
602
  if (transit)
3821
128
    assert(transit->refcnt > 0);
3822
602
  if (attr->encap_subtlvs)
3823
5
    assert(attr->encap_subtlvs->refcnt > 0);
3824
602
#ifdef ENABLE_BGP_VNC
3825
602
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
3826
602
    bgp_attr_get_vnc_subtlvs(attr);
3827
3828
602
  if (vnc_subtlvs)
3829
0
    assert(vnc_subtlvs->refcnt > 0);
3830
602
#endif
3831
3832
602
  return ret;
3833
602
}
3834
3835
/*
3836
 * Extract the tunnel type from extended community
3837
 */
3838
void bgp_attr_extcom_tunnel_type(struct attr *attr,
3839
         bgp_encap_types *tunnel_type)
3840
109
{
3841
109
  struct ecommunity *ecom;
3842
109
  uint32_t i;
3843
3844
109
  if (!attr)
3845
0
    return;
3846
3847
109
  ecom = bgp_attr_get_ecommunity(attr);
3848
109
  if (!ecom || !ecom->size)
3849
0
    return;
3850
3851
10.0k
  for (i = 0; i < ecom->size; i++) {
3852
9.97k
    uint8_t *pnt;
3853
9.97k
    uint8_t type, sub_type;
3854
3855
9.97k
    pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3856
9.97k
    type = pnt[0];
3857
9.97k
    sub_type = pnt[1];
3858
9.97k
    if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3859
213
          sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3860
9.97k
      continue;
3861
2
    *tunnel_type = ((pnt[6] << 8) | pnt[7]);
3862
2
    return;
3863
9.97k
  }
3864
3865
107
  return;
3866
109
}
3867
3868
size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
3869
             safi_t safi, struct bpacket_attr_vec_arr *vecarr,
3870
             struct attr *attr)
3871
0
{
3872
0
  size_t sizep;
3873
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
3874
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
3875
0
  afi_t nh_afi;
3876
3877
  /* Set extended bit always to encode the attribute length as 2 bytes */
3878
0
  stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
3879
0
  stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3880
0
  sizep = stream_get_endp(s);
3881
0
  stream_putw(s, 0); /* Marker: Attribute length. */
3882
3883
3884
  /* Convert AFI, SAFI to values for packet. */
3885
0
  bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
3886
3887
0
  stream_putw(s, pkt_afi);  /* AFI */
3888
0
  stream_putc(s, pkt_safi); /* SAFI */
3889
3890
  /* Nexthop AFI */
3891
0
  if (afi == AFI_IP
3892
0
      && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST
3893
0
    || safi == SAFI_MPLS_VPN || safi == SAFI_MULTICAST))
3894
0
    nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
3895
0
  else if (safi == SAFI_FLOWSPEC)
3896
0
    nh_afi = afi;
3897
0
  else
3898
0
    nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
3899
3900
  /* Nexthop */
3901
0
  bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr);
3902
0
  switch (nh_afi) {
3903
0
  case AFI_IP:
3904
0
    switch (safi) {
3905
0
    case SAFI_UNICAST:
3906
0
    case SAFI_MULTICAST:
3907
0
    case SAFI_LABELED_UNICAST:
3908
0
      stream_putc(s, 4);
3909
0
      stream_put_ipv4(s, attr->nexthop.s_addr);
3910
0
      break;
3911
0
    case SAFI_MPLS_VPN:
3912
0
      stream_putc(s, 12);
3913
0
      stream_putl(s, 0); /* RD = 0, per RFC */
3914
0
      stream_putl(s, 0);
3915
0
      stream_put(s, &attr->mp_nexthop_global_in, 4);
3916
0
      break;
3917
0
    case SAFI_ENCAP:
3918
0
    case SAFI_EVPN:
3919
0
      stream_putc(s, 4);
3920
0
      stream_put(s, &attr->mp_nexthop_global_in, 4);
3921
0
      break;
3922
0
    case SAFI_FLOWSPEC:
3923
0
      if (attr->mp_nexthop_len == 0)
3924
0
        stream_putc(s, 0); /* no nexthop for flowspec */
3925
0
      else {
3926
0
        stream_putc(s, attr->mp_nexthop_len);
3927
0
        stream_put_ipv4(s, attr->nexthop.s_addr);
3928
0
      }
3929
0
      break;
3930
0
    case SAFI_UNSPEC:
3931
0
    case SAFI_MAX:
3932
0
      assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3933
0
      break;
3934
0
    }
3935
0
    break;
3936
0
  case AFI_IP6:
3937
0
    switch (safi) {
3938
0
    case SAFI_UNICAST:
3939
0
    case SAFI_MULTICAST:
3940
0
    case SAFI_LABELED_UNICAST:
3941
0
    case SAFI_EVPN: {
3942
0
      if (attr->mp_nexthop_len
3943
0
          == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3944
0
        stream_putc(s,
3945
0
              BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
3946
0
        stream_put(s, &attr->mp_nexthop_global,
3947
0
             IPV6_MAX_BYTELEN);
3948
0
        stream_put(s, &attr->mp_nexthop_local,
3949
0
             IPV6_MAX_BYTELEN);
3950
0
      } else {
3951
0
        stream_putc(s, IPV6_MAX_BYTELEN);
3952
0
        stream_put(s, &attr->mp_nexthop_global,
3953
0
             IPV6_MAX_BYTELEN);
3954
0
      }
3955
0
    } break;
3956
0
    case SAFI_MPLS_VPN: {
3957
0
      if (attr->mp_nexthop_len ==
3958
0
          BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
3959
0
        stream_putc(s, attr->mp_nexthop_len);
3960
0
      else
3961
0
        stream_putc(s, BGP_ATTR_NHLEN_VPNV6_GLOBAL);
3962
0
      stream_putl(s, 0); /* RD = 0, per RFC */
3963
0
      stream_putl(s, 0);
3964
0
      stream_put(s, &attr->mp_nexthop_global,
3965
0
           IPV6_MAX_BYTELEN);
3966
0
      if (attr->mp_nexthop_len ==
3967
0
          BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
3968
0
        stream_putl(s, 0); /* RD = 0, per RFC */
3969
0
        stream_putl(s, 0);
3970
0
        stream_put(s, &attr->mp_nexthop_local,
3971
0
             IPV6_MAX_BYTELEN);
3972
0
      }
3973
0
    } break;
3974
0
    case SAFI_ENCAP:
3975
0
      stream_putc(s, IPV6_MAX_BYTELEN);
3976
0
      stream_put(s, &attr->mp_nexthop_global,
3977
0
           IPV6_MAX_BYTELEN);
3978
0
      break;
3979
0
    case SAFI_FLOWSPEC:
3980
0
      stream_putc(s, 0); /* no nexthop for flowspec */
3981
0
      break;
3982
0
    case SAFI_UNSPEC:
3983
0
    case SAFI_MAX:
3984
0
      assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3985
0
      break;
3986
0
    }
3987
0
    break;
3988
0
  case AFI_L2VPN:
3989
0
    if (safi != SAFI_FLOWSPEC)
3990
0
      flog_err(
3991
0
        EC_BGP_ATTR_NH_SEND_LEN,
3992
0
        "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3993
0
        peer->host, afi, safi, attr->mp_nexthop_len);
3994
0
    break;
3995
0
  case AFI_UNSPEC:
3996
0
  case AFI_MAX:
3997
0
    assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
3998
0
    break;
3999
0
  }
4000
4001
  /* SNPA */
4002
0
  stream_putc(s, 0);
4003
0
  return sizep;
4004
0
}
4005
4006
void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
4007
            const struct prefix *p,
4008
            const struct prefix_rd *prd, mpls_label_t *label,
4009
            uint32_t num_labels, bool addpath_capable,
4010
            uint32_t addpath_tx_id, struct attr *attr)
4011
0
{
4012
0
  switch (safi) {
4013
0
  case SAFI_UNSPEC:
4014
0
  case SAFI_MAX:
4015
0
    assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4016
0
    break;
4017
0
  case SAFI_MPLS_VPN:
4018
0
    if (addpath_capable)
4019
0
      stream_putl(s, addpath_tx_id);
4020
    /* Label, RD, Prefix write. */
4021
0
    stream_putc(s, p->prefixlen + 88);
4022
0
    stream_put(s, label, BGP_LABEL_BYTES);
4023
0
    stream_put(s, prd->val, 8);
4024
0
    stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
4025
0
    break;
4026
0
  case SAFI_EVPN:
4027
0
    if (afi == AFI_L2VPN)
4028
      /* EVPN prefix - contents depend on type */
4029
0
      bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
4030
0
                 attr, addpath_capable,
4031
0
                 addpath_tx_id);
4032
0
    else
4033
0
      assert(!"Add encoding bits here for other AFI's");
4034
0
    break;
4035
0
  case SAFI_LABELED_UNICAST:
4036
    /* Prefix write with label. */
4037
0
    stream_put_labeled_prefix(s, p, label, addpath_capable,
4038
0
            addpath_tx_id);
4039
0
    break;
4040
0
  case SAFI_FLOWSPEC:
4041
0
    stream_putc(s, p->u.prefix_flowspec.prefixlen);
4042
0
    stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
4043
0
         p->u.prefix_flowspec.prefixlen);
4044
0
    break;
4045
4046
0
  case SAFI_UNICAST:
4047
0
  case SAFI_MULTICAST:
4048
0
    stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
4049
0
    break;
4050
0
  case SAFI_ENCAP:
4051
0
    assert(!"Please add proper encoding of SAFI_ENCAP");
4052
0
    break;
4053
0
  }
4054
0
}
4055
4056
size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
4057
             const struct prefix *p)
4058
0
{
4059
0
  int size = PSIZE(p->prefixlen);
4060
4061
0
  switch (safi) {
4062
0
  case SAFI_UNSPEC:
4063
0
  case SAFI_MAX:
4064
0
    assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4065
0
    break;
4066
0
  case SAFI_UNICAST:
4067
0
  case SAFI_MULTICAST:
4068
0
    break;
4069
0
  case SAFI_MPLS_VPN:
4070
0
    size += 88;
4071
0
    break;
4072
0
  case SAFI_ENCAP:
4073
    /* This has to be wrong, but I don't know what to put here */
4074
0
    assert(!"Do we try to use this?");
4075
0
    break;
4076
0
  case SAFI_LABELED_UNICAST:
4077
0
    size += BGP_LABEL_BYTES;
4078
0
    break;
4079
0
  case SAFI_EVPN:
4080
    /*
4081
     * TODO: Maximum possible for type-2, type-3 and type-5
4082
     */
4083
0
    if (afi == AFI_L2VPN)
4084
0
      size += 232;
4085
0
    else
4086
0
      assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4087
0
    break;
4088
0
  case SAFI_FLOWSPEC:
4089
0
    size = ((struct prefix_fs *)p)->prefix.prefixlen;
4090
0
    break;
4091
0
  }
4092
4093
0
  return size;
4094
0
}
4095
4096
/*
4097
 * Encodes the tunnel encapsulation attribute,
4098
 * and with ENABLE_BGP_VNC the VNC attribute which uses
4099
 * almost the same TLV format
4100
 */
4101
static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
4102
          struct stream *s, struct attr *attr,
4103
          uint8_t attrtype)
4104
0
{
4105
0
  unsigned int attrlenfield = 0;
4106
0
  unsigned int attrhdrlen = 0;
4107
0
  struct bgp_attr_encap_subtlv *subtlvs;
4108
0
  struct bgp_attr_encap_subtlv *st;
4109
0
  const char *attrname;
4110
4111
0
  if (!attr || (attrtype == BGP_ATTR_ENCAP
4112
0
          && (!attr->encap_tunneltype
4113
0
        || attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS)))
4114
0
    return;
4115
4116
0
  switch (attrtype) {
4117
0
  case BGP_ATTR_ENCAP:
4118
0
    attrname = "Tunnel Encap";
4119
0
    subtlvs = attr->encap_subtlvs;
4120
0
    if (subtlvs == NULL) /* nothing to do */
4121
0
      return;
4122
    /*
4123
     * The tunnel encap attr has an "outer" tlv.
4124
     * T = tunneltype,
4125
     * L = total length of subtlvs,
4126
     * V = concatenated subtlvs.
4127
     */
4128
0
    attrlenfield = 2 + 2; /* T + L */
4129
0
    attrhdrlen = 1 + 1;   /* subTLV T + L */
4130
0
    break;
4131
4132
#ifdef ENABLE_BGP_VNC_ATTR
4133
  case BGP_ATTR_VNC:
4134
    attrname = "VNC";
4135
    subtlvs = bgp_attr_get_vnc_subtlvs(attr);
4136
    if (subtlvs == NULL) /* nothing to do */
4137
      return;
4138
    attrlenfield = 0;   /* no outer T + L */
4139
    attrhdrlen = 2 + 2; /* subTLV T + L */
4140
    break;
4141
#endif
4142
4143
0
  default:
4144
0
    assert(0);
4145
0
  }
4146
4147
  /* compute attr length */
4148
0
  for (st = subtlvs; st; st = st->next) {
4149
0
    attrlenfield += (attrhdrlen + st->length);
4150
0
  }
4151
4152
0
  if (attrlenfield > 0xffff) {
4153
0
    zlog_info("%s attribute is too long (length=%d), can't send it",
4154
0
        attrname, attrlenfield);
4155
0
    return;
4156
0
  }
4157
4158
0
  if (attrlenfield > 0xff) {
4159
    /* 2-octet length field */
4160
0
    stream_putc(s,
4161
0
          BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4162
0
            | BGP_ATTR_FLAG_EXTLEN);
4163
0
    stream_putc(s, attrtype);
4164
0
    stream_putw(s, attrlenfield & 0xffff);
4165
0
  } else {
4166
    /* 1-octet length field */
4167
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
4168
0
    stream_putc(s, attrtype);
4169
0
    stream_putc(s, attrlenfield & 0xff);
4170
0
  }
4171
4172
0
  if (attrtype == BGP_ATTR_ENCAP) {
4173
    /* write outer T+L */
4174
0
    stream_putw(s, attr->encap_tunneltype);
4175
0
    stream_putw(s, attrlenfield - 4);
4176
0
  }
4177
4178
  /* write each sub-tlv */
4179
0
  for (st = subtlvs; st; st = st->next) {
4180
0
    if (attrtype == BGP_ATTR_ENCAP) {
4181
0
      stream_putc(s, st->type);
4182
0
      stream_putc(s, st->length);
4183
0
#ifdef ENABLE_BGP_VNC
4184
0
    } else {
4185
0
      stream_putw(s, st->type);
4186
0
      stream_putw(s, st->length);
4187
0
#endif
4188
0
    }
4189
0
    stream_put(s, st->value, st->length);
4190
0
  }
4191
0
}
4192
4193
void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
4194
0
{
4195
  /* Set MP attribute length. Don't count the (2) bytes used to encode
4196
     the attr length */
4197
0
  stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
4198
0
}
4199
4200
static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
4201
0
{
4202
0
  if (!BGP_AS_IS_PRIVATE(peer->local_as)
4203
0
      || (BGP_AS_IS_PRIVATE(peer->local_as)
4204
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4205
0
             PEER_FLAG_REMOVE_PRIVATE_AS)
4206
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4207
0
             PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
4208
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4209
0
             PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
4210
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4211
0
             PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
4212
0
    return true;
4213
0
  return false;
4214
0
}
4215
4216
/* Make attribute packet. */
4217
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
4218
        struct stream *s, struct attr *attr,
4219
        struct bpacket_attr_vec_arr *vecarr,
4220
        struct prefix *p, afi_t afi, safi_t safi,
4221
        struct peer *from, struct prefix_rd *prd,
4222
        mpls_label_t *label, uint32_t num_labels,
4223
        bool addpath_capable, uint32_t addpath_tx_id,
4224
        struct bgp_path_info *bpi)
4225
0
{
4226
0
  size_t cp;
4227
0
  size_t aspath_sizep;
4228
0
  struct aspath *aspath;
4229
0
  int send_as4_path = 0;
4230
0
  int send_as4_aggregator = 0;
4231
0
  bool use32bit = CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
4232
0
      && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV);
4233
4234
0
  if (!bgp)
4235
0
    bgp = peer->bgp;
4236
4237
  /* Remember current pointer. */
4238
0
  cp = stream_get_endp(s);
4239
4240
0
  if (p
4241
0
      && !((afi == AFI_IP && safi == SAFI_UNICAST)
4242
0
     && !peer_cap_enhe(peer, afi, safi))) {
4243
0
    size_t mpattrlen_pos = 0;
4244
4245
0
    mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
4246
0
              vecarr, attr);
4247
0
    bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
4248
0
           num_labels, addpath_capable,
4249
0
           addpath_tx_id, attr);
4250
0
    bgp_packet_mpattr_end(s, mpattrlen_pos);
4251
0
  }
4252
4253
  /* Origin attribute. */
4254
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS);
4255
0
  stream_putc(s, BGP_ATTR_ORIGIN);
4256
0
  stream_putc(s, 1);
4257
0
  stream_putc(s, attr->origin);
4258
4259
  /* AS path attribute. */
4260
4261
  /* If remote-peer is EBGP */
4262
0
  if (peer->sort == BGP_PEER_EBGP
4263
0
      && (!CHECK_FLAG(peer->af_flags[afi][safi],
4264
0
          PEER_FLAG_AS_PATH_UNCHANGED)
4265
0
    || attr->aspath->segments == NULL)
4266
0
      && (!CHECK_FLAG(peer->af_flags[afi][safi],
4267
0
          PEER_FLAG_RSERVER_CLIENT))) {
4268
0
    aspath = aspath_dup(attr->aspath);
4269
4270
    /* Even though we may not be configured for confederations we
4271
     * may have
4272
     * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4273
0
    aspath = aspath_delete_confed_seq(aspath);
4274
4275
0
    if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
4276
      /* A confed member, so we need to do the
4277
       * AS_CONFED_SEQUENCE thing if it's outside a common
4278
       * administration.
4279
       * Configured confederation peers MUST be validated
4280
       * under BGP_PEER_CONFED, but if we have configured
4281
       * remote-as as AS_EXTERNAL, we need to check again
4282
       * if the peer belongs to us.
4283
       */
4284
0
      if (bgp_confederation_peers_check(bgp, peer->as)) {
4285
0
        aspath = aspath_add_confed_seq(aspath,
4286
0
                     peer->local_as);
4287
0
      } else {
4288
        /* Stuff our path CONFED_ID on the front */
4289
0
        aspath = aspath_add_seq(aspath, bgp->confed_id);
4290
0
      }
4291
0
    } else {
4292
0
      if (peer->change_local_as) {
4293
        /* If replace-as is specified, we only use the
4294
           change_local_as when
4295
           advertising routes. */
4296
0
        if (!CHECK_FLAG(peer->flags,
4297
0
            PEER_FLAG_LOCAL_AS_REPLACE_AS))
4298
0
          if (bgp_append_local_as(peer, afi,
4299
0
                safi))
4300
0
            aspath = aspath_add_seq(
4301
0
              aspath, peer->local_as);
4302
0
        aspath = aspath_add_seq(aspath,
4303
0
              peer->change_local_as);
4304
0
      } else {
4305
0
        aspath = aspath_add_seq(aspath, peer->local_as);
4306
0
      }
4307
0
    }
4308
0
  } else if (peer->sort == BGP_PEER_CONFED) {
4309
    /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4310
     * thing */
4311
0
    aspath = aspath_dup(attr->aspath);
4312
0
    aspath = aspath_add_confed_seq(aspath, peer->local_as);
4313
0
  } else
4314
0
    aspath = attr->aspath;
4315
4316
  /* If peer is not AS4 capable, then:
4317
   * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4318
   *   but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4319
   * segment
4320
   *   types are in it (i.e. exclude them if they are there)
4321
   *   AND do this only if there is at least one asnum > 65535 in the
4322
   * path!
4323
   * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4324
   * change
4325
   *   all ASnums > 65535 to BGP_AS_TRANS
4326
   */
4327
4328
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4329
0
  stream_putc(s, BGP_ATTR_AS_PATH);
4330
0
  aspath_sizep = stream_get_endp(s);
4331
0
  stream_putw(s, 0);
4332
0
  stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, use32bit));
4333
4334
  /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4335
   * in the path
4336
   */
4337
0
  if (!use32bit && aspath_has_as4(aspath))
4338
0
    send_as4_path =
4339
0
      1; /* we'll do this later, at the correct place */
4340
4341
  /* Nexthop attribute. */
4342
0
  if (afi == AFI_IP && safi == SAFI_UNICAST
4343
0
      && !peer_cap_enhe(peer, afi, safi)) {
4344
0
    afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
4345
4346
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
4347
0
      stream_putc(s, BGP_ATTR_FLAG_TRANS);
4348
0
      stream_putc(s, BGP_ATTR_NEXT_HOP);
4349
0
      bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4350
0
                 attr);
4351
0
      stream_putc(s, 4);
4352
0
      stream_put_ipv4(s, attr->nexthop.s_addr);
4353
0
    } else if (peer_cap_enhe(from, afi, safi)
4354
0
         || (nh_afi == AFI_IP6)) {
4355
      /*
4356
       * Likely this is the case when an IPv4 prefix was
4357
       * received with Extended Next-hop capability in this
4358
       * or another vrf and is now being advertised to
4359
       * non-ENHE peers. Since peer_cap_enhe only checks
4360
       * peers in this vrf, also check the nh_afi to catch
4361
       * the case where the originator was in another vrf.
4362
       * Setting the mandatory (ipv4) next-hop attribute here
4363
       * to enable implicit next-hop self with correct A-F
4364
       * (ipv4 address family).
4365
       */
4366
0
      stream_putc(s, BGP_ATTR_FLAG_TRANS);
4367
0
      stream_putc(s, BGP_ATTR_NEXT_HOP);
4368
0
      bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4369
0
                 NULL);
4370
0
      stream_putc(s, 4);
4371
0
      stream_put_ipv4(s, 0);
4372
0
    }
4373
0
  }
4374
4375
  /* MED attribute. */
4376
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
4377
0
      || bgp->maxmed_active) {
4378
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4379
0
    stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4380
0
    stream_putc(s, 4);
4381
0
    stream_putl(s, (bgp->maxmed_active ? bgp->maxmed_value
4382
0
               : attr->med));
4383
0
  }
4384
4385
  /* Local preference. */
4386
0
  if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
4387
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4388
0
    stream_putc(s, BGP_ATTR_LOCAL_PREF);
4389
0
    stream_putc(s, 4);
4390
0
    stream_putl(s, attr->local_pref);
4391
0
  }
4392
4393
  /* Atomic aggregate. */
4394
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4395
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4396
0
    stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4397
0
    stream_putc(s, 0);
4398
0
  }
4399
4400
  /* Aggregator. */
4401
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4402
    /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4403
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4404
0
    stream_putc(s, BGP_ATTR_AGGREGATOR);
4405
4406
0
    if (use32bit) {
4407
      /* AS4 capable peer */
4408
0
      stream_putc(s, 8);
4409
0
      stream_putl(s, attr->aggregator_as);
4410
0
    } else {
4411
      /* 2-byte AS peer */
4412
0
      stream_putc(s, 6);
4413
4414
      /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4415
       * used? */
4416
0
      if (attr->aggregator_as > UINT16_MAX) {
4417
0
        stream_putw(s, BGP_AS_TRANS);
4418
4419
        /* we have to send AS4_AGGREGATOR, too.
4420
         * we'll do that later in order to send
4421
         * attributes in ascending
4422
         * order.
4423
         */
4424
0
        send_as4_aggregator = 1;
4425
0
      } else
4426
0
        stream_putw(s, (uint16_t)attr->aggregator_as);
4427
0
    }
4428
0
    stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4429
0
  }
4430
4431
  /* Community attribute. */
4432
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
4433
0
      && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
4434
0
    struct community *comm = NULL;
4435
4436
0
    comm = bgp_attr_get_community(attr);
4437
0
    if (comm->size * 4 > 255) {
4438
0
      stream_putc(s,
4439
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4440
0
              | BGP_ATTR_FLAG_EXTLEN);
4441
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4442
0
      stream_putw(s, comm->size * 4);
4443
0
    } else {
4444
0
      stream_putc(s,
4445
0
            BGP_ATTR_FLAG_OPTIONAL
4446
0
              | BGP_ATTR_FLAG_TRANS);
4447
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4448
0
      stream_putc(s, comm->size * 4);
4449
0
    }
4450
0
    stream_put(s, comm->val, comm->size * 4);
4451
0
  }
4452
4453
  /*
4454
   * Large Community attribute.
4455
   */
4456
0
  if (CHECK_FLAG(peer->af_flags[afi][safi],
4457
0
           PEER_FLAG_SEND_LARGE_COMMUNITY)
4458
0
      && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
4459
0
    if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
4460
0
      stream_putc(s,
4461
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4462
0
              | BGP_ATTR_FLAG_EXTLEN);
4463
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4464
0
      stream_putw(s,
4465
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4466
0
    } else {
4467
0
      stream_putc(s,
4468
0
            BGP_ATTR_FLAG_OPTIONAL
4469
0
              | BGP_ATTR_FLAG_TRANS);
4470
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4471
0
      stream_putc(s,
4472
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4473
0
    }
4474
0
    stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4475
0
         lcom_length(bgp_attr_get_lcommunity(attr)));
4476
0
  }
4477
4478
  /* Route Reflector. */
4479
0
  if (peer->sort == BGP_PEER_IBGP && from
4480
0
      && from->sort == BGP_PEER_IBGP) {
4481
0
    struct cluster_list *cluster = bgp_attr_get_cluster(attr);
4482
4483
    /* Originator ID. */
4484
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4485
0
    stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
4486
0
    stream_putc(s, 4);
4487
4488
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
4489
0
      stream_put_in_addr(s, &attr->originator_id);
4490
0
    else
4491
0
      stream_put_in_addr(s, &from->remote_id);
4492
4493
    /* Cluster list. */
4494
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4495
0
    stream_putc(s, BGP_ATTR_CLUSTER_LIST);
4496
4497
0
    if (cluster) {
4498
0
      stream_putc(s, cluster->length + 4);
4499
      /* If this peer configuration's parent BGP has
4500
       * cluster_id. */
4501
0
      if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4502
0
        stream_put_in_addr(s, &bgp->cluster_id);
4503
0
      else
4504
0
        stream_put_in_addr(s, &bgp->router_id);
4505
0
      stream_put(s, cluster->list, cluster->length);
4506
0
    } else {
4507
0
      stream_putc(s, 4);
4508
      /* If this peer configuration's parent BGP has
4509
       * cluster_id. */
4510
0
      if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4511
0
        stream_put_in_addr(s, &bgp->cluster_id);
4512
0
      else
4513
0
        stream_put_in_addr(s, &bgp->router_id);
4514
0
    }
4515
0
  }
4516
4517
  /* Extended Communities attribute. */
4518
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
4519
0
      && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4520
0
    struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
4521
0
    bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
4522
0
                PEER_FLAG_RSERVER_CLIENT) &&
4523
0
           from &&
4524
0
           CHECK_FLAG(from->af_flags[afi][safi],
4525
0
                PEER_FLAG_RSERVER_CLIENT);
4526
4527
0
    if (peer->sort == BGP_PEER_IBGP ||
4528
0
        peer->sort == BGP_PEER_CONFED || transparent) {
4529
0
      if (ecomm->size * 8 > 255) {
4530
0
        stream_putc(s,
4531
0
              BGP_ATTR_FLAG_OPTIONAL
4532
0
                | BGP_ATTR_FLAG_TRANS
4533
0
                | BGP_ATTR_FLAG_EXTLEN);
4534
0
        stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4535
0
        stream_putw(s, ecomm->size * 8);
4536
0
      } else {
4537
0
        stream_putc(s,
4538
0
              BGP_ATTR_FLAG_OPTIONAL
4539
0
                | BGP_ATTR_FLAG_TRANS);
4540
0
        stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4541
0
        stream_putc(s, ecomm->size * 8);
4542
0
      }
4543
0
      stream_put(s, ecomm->val, ecomm->size * 8);
4544
0
    } else {
4545
0
      uint8_t *pnt;
4546
0
      int tbit;
4547
0
      int ecom_tr_size = 0;
4548
0
      uint32_t i;
4549
4550
0
      for (i = 0; i < ecomm->size; i++) {
4551
0
        pnt = ecomm->val + (i * 8);
4552
0
        tbit = *pnt;
4553
4554
0
        if (CHECK_FLAG(tbit,
4555
0
                 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4556
0
          continue;
4557
4558
0
        ecom_tr_size++;
4559
0
      }
4560
4561
0
      if (ecom_tr_size) {
4562
0
        if (ecom_tr_size * 8 > 255) {
4563
0
          stream_putc(
4564
0
            s,
4565
0
            BGP_ATTR_FLAG_OPTIONAL
4566
0
              | BGP_ATTR_FLAG_TRANS
4567
0
              | BGP_ATTR_FLAG_EXTLEN);
4568
0
          stream_putc(s,
4569
0
                BGP_ATTR_EXT_COMMUNITIES);
4570
0
          stream_putw(s, ecom_tr_size * 8);
4571
0
        } else {
4572
0
          stream_putc(
4573
0
            s,
4574
0
            BGP_ATTR_FLAG_OPTIONAL
4575
0
              | BGP_ATTR_FLAG_TRANS);
4576
0
          stream_putc(s,
4577
0
                BGP_ATTR_EXT_COMMUNITIES);
4578
0
          stream_putc(s, ecom_tr_size * 8);
4579
0
        }
4580
4581
0
        for (i = 0; i < ecomm->size; i++) {
4582
0
          pnt = ecomm->val + (i * 8);
4583
0
          tbit = *pnt;
4584
4585
0
          if (CHECK_FLAG(
4586
0
                tbit,
4587
0
                ECOMMUNITY_FLAG_NON_TRANSITIVE))
4588
0
            continue;
4589
4590
0
          stream_put(s, pnt, 8);
4591
0
        }
4592
0
      }
4593
0
    }
4594
0
  }
4595
4596
  /* Label index attribute. */
4597
0
  if (safi == SAFI_LABELED_UNICAST) {
4598
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4599
0
      uint32_t label_index;
4600
4601
0
      label_index = attr->label_index;
4602
4603
0
      if (label_index != BGP_INVALID_LABEL_INDEX) {
4604
0
        stream_putc(s,
4605
0
              BGP_ATTR_FLAG_OPTIONAL
4606
0
                | BGP_ATTR_FLAG_TRANS);
4607
0
        stream_putc(s, BGP_ATTR_PREFIX_SID);
4608
0
        stream_putc(s, 10);
4609
0
        stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
4610
0
        stream_putw(s,
4611
0
              BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
4612
0
        stream_putc(s, 0); // reserved
4613
0
        stream_putw(s, 0); // flags
4614
0
        stream_putl(s, label_index);
4615
0
      }
4616
0
    }
4617
0
  }
4618
4619
  /* SRv6 Service Information Attribute. */
4620
0
  if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) {
4621
0
    if (attr->srv6_l3vpn) {
4622
0
      uint8_t subtlv_len =
4623
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4624
0
        + BGP_ATTR_MIN_LEN
4625
0
        + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH;
4626
0
      uint8_t tlv_len = subtlv_len + BGP_ATTR_MIN_LEN + 1;
4627
0
      uint8_t attr_len = tlv_len + BGP_ATTR_MIN_LEN;
4628
0
      stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4629
0
                 | BGP_ATTR_FLAG_TRANS);
4630
0
      stream_putc(s, BGP_ATTR_PREFIX_SID);
4631
0
      stream_putc(s, attr_len);
4632
0
      stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE);
4633
0
      stream_putw(s, tlv_len);
4634
0
      stream_putc(s, 0); /* reserved */
4635
0
      stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO);
4636
0
      stream_putw(s, subtlv_len);
4637
0
      stream_putc(s, 0);      /* reserved */
4638
0
      stream_put(s, &attr->srv6_l3vpn->sid,
4639
0
           sizeof(attr->srv6_l3vpn->sid)); /* sid */
4640
0
      stream_putc(s, 0);      /* sid_flags */
4641
0
      stream_putw(s,
4642
0
            attr->srv6_l3vpn
4643
0
              ->endpoint_behavior); /* endpoint */
4644
0
      stream_putc(s, 0);      /* reserved */
4645
0
      stream_putc(
4646
0
        s,
4647
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE);
4648
0
      stream_putw(
4649
0
        s,
4650
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH);
4651
0
      stream_putc(s, attr->srv6_l3vpn->loc_block_len);
4652
0
      stream_putc(s, attr->srv6_l3vpn->loc_node_len);
4653
0
      stream_putc(s, attr->srv6_l3vpn->func_len);
4654
0
      stream_putc(s, attr->srv6_l3vpn->arg_len);
4655
0
      stream_putc(s, attr->srv6_l3vpn->transposition_len);
4656
0
      stream_putc(s, attr->srv6_l3vpn->transposition_offset);
4657
0
    } else if (attr->srv6_vpn) {
4658
0
      stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4659
0
                 | BGP_ATTR_FLAG_TRANS);
4660
0
      stream_putc(s, BGP_ATTR_PREFIX_SID);
4661
0
      stream_putc(s, 22);     /* tlv len */
4662
0
      stream_putc(s, BGP_PREFIX_SID_VPN_SID);
4663
0
      stream_putw(s, 0x13);   /* tlv len */
4664
0
      stream_putc(s, 0x00);   /* reserved */
4665
0
      stream_putc(s, 0x01);   /* sid_type */
4666
0
      stream_putc(s, 0x00);   /* sif_flags */
4667
0
      stream_put(s, &attr->srv6_vpn->sid,
4668
0
           sizeof(attr->srv6_vpn->sid)); /* sid */
4669
0
    }
4670
0
  }
4671
4672
0
  if (send_as4_path) {
4673
    /* If the peer is NOT As4 capable, AND */
4674
    /* there are ASnums > 65535 in path  THEN
4675
     * give out AS4_PATH */
4676
4677
    /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4678
     * path segments!
4679
     * Hm, I wonder...  confederation things *should* only be at
4680
     * the beginning of an aspath, right?  Then we should use
4681
     * aspath_delete_confed_seq for this, because it is already
4682
     * there! (JK)
4683
     * Folks, talk to me: what is reasonable here!?
4684
     */
4685
4686
    /* Make sure dup aspath before the modification */
4687
0
    if (aspath == attr->aspath)
4688
0
      aspath = aspath_dup(attr->aspath);
4689
0
    aspath = aspath_delete_confed_seq(aspath);
4690
4691
0
    stream_putc(s,
4692
0
          BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4693
0
            | BGP_ATTR_FLAG_EXTLEN);
4694
0
    stream_putc(s, BGP_ATTR_AS4_PATH);
4695
0
    aspath_sizep = stream_get_endp(s);
4696
0
    stream_putw(s, 0);
4697
0
    stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, 1));
4698
0
  }
4699
4700
0
  if (aspath != attr->aspath)
4701
0
    aspath_free(aspath);
4702
4703
0
  if (send_as4_aggregator) {
4704
    /* send AS4_AGGREGATOR, at this place */
4705
    /* this section of code moved here in order to ensure the
4706
     * correct
4707
     * *ascending* order of attributes
4708
     */
4709
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4710
0
    stream_putc(s, BGP_ATTR_AS4_AGGREGATOR);
4711
0
    stream_putc(s, 8);
4712
0
    stream_putl(s, attr->aggregator_as);
4713
0
    stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4714
0
  }
4715
4716
0
  if (((afi == AFI_IP || afi == AFI_IP6)
4717
0
       && (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
4718
0
      || (afi == AFI_L2VPN && safi == SAFI_EVPN)) {
4719
    /* Tunnel Encap attribute */
4720
0
    bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
4721
4722
#ifdef ENABLE_BGP_VNC_ATTR
4723
    /* VNC attribute */
4724
    bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
4725
#endif
4726
0
  }
4727
4728
  /* PMSI Tunnel */
4729
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
4730
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4731
0
    stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
4732
0
    stream_putc(s, 9); // Length
4733
0
    stream_putc(s, 0); // Flags
4734
0
    stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
4735
0
    stream_put(s, &(attr->label),
4736
0
         BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
4737
0
    stream_put_ipv4(s, attr->nexthop.s_addr);
4738
    // Unicast tunnel endpoint IP address
4739
0
  }
4740
4741
  /* OTC */
4742
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
4743
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4744
0
    stream_putc(s, BGP_ATTR_OTC);
4745
0
    stream_putc(s, 4);
4746
0
    stream_putl(s, attr->otc);
4747
0
  }
4748
4749
  /* AIGP */
4750
0
  if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
4751
0
      (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
4752
0
       peer->sort != BGP_PEER_EBGP)) {
4753
    /* At the moment only AIGP Metric TLV exists for AIGP
4754
     * attribute. If more comes in, do not forget to update
4755
     * attr_len variable to include new ones.
4756
     */
4757
0
    uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
4758
4759
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4760
0
    stream_putc(s, BGP_ATTR_AIGP);
4761
0
    stream_putc(s, attr_len);
4762
0
    stream_put_bgp_aigp_tlv_metric(s, bpi);
4763
0
  }
4764
4765
  /* Unknown transit attribute. */
4766
0
  struct transit *transit = bgp_attr_get_transit(attr);
4767
4768
0
  if (transit)
4769
0
    stream_put(s, transit->val, transit->length);
4770
4771
  /* Return total size of attribute. */
4772
0
  return stream_get_endp(s) - cp;
4773
0
}
4774
4775
size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
4776
0
{
4777
0
  unsigned long attrlen_pnt;
4778
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
4779
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
4780
4781
  /* Set extended bit always to encode the attribute length as 2 bytes */
4782
0
  stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
4783
0
  stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
4784
4785
0
  attrlen_pnt = stream_get_endp(s);
4786
0
  stream_putw(s, 0); /* Length of this attribute. */
4787
4788
  /* Convert AFI, SAFI to values for packet. */
4789
0
  bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
4790
4791
0
  stream_putw(s, pkt_afi);
4792
0
  stream_putc(s, pkt_safi);
4793
4794
0
  return attrlen_pnt;
4795
0
}
4796
4797
void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
4798
         afi_t afi, safi_t safi,
4799
         const struct prefix_rd *prd,
4800
         mpls_label_t *label, uint32_t num_labels,
4801
         bool addpath_capable, uint32_t addpath_tx_id,
4802
         struct attr *attr)
4803
0
{
4804
0
  uint8_t wlabel[4] = {0x80, 0x00, 0x00};
4805
4806
0
  if (safi == SAFI_LABELED_UNICAST) {
4807
0
    label = (mpls_label_t *)wlabel;
4808
0
    num_labels = 1;
4809
0
  }
4810
4811
0
  bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
4812
0
         addpath_capable, addpath_tx_id, attr);
4813
0
}
4814
4815
void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)
4816
0
{
4817
0
  bgp_packet_mpattr_end(s, attrlen_pnt);
4818
0
}
4819
4820
/* Initialization of attribute. */
4821
void bgp_attr_init(void)
4822
1
{
4823
1
  aspath_init();
4824
1
  attrhash_init();
4825
1
  community_init();
4826
1
  ecommunity_init();
4827
1
  lcommunity_init();
4828
1
  cluster_init();
4829
1
  transit_init();
4830
1
  encap_init();
4831
1
  srv6_init();
4832
1
}
4833
4834
void bgp_attr_finish(void)
4835
0
{
4836
0
  aspath_finish();
4837
0
  attrhash_finish();
4838
0
  community_finish();
4839
0
  ecommunity_finish();
4840
0
  lcommunity_finish();
4841
0
  cluster_finish();
4842
0
  transit_finish();
4843
0
  encap_finish();
4844
0
  srv6_finish();
4845
0
}
4846
4847
/* Make attribute packet. */
4848
void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
4849
        const struct prefix *prefix)
4850
0
{
4851
0
  unsigned long cp;
4852
0
  unsigned long len;
4853
0
  size_t aspath_lenp;
4854
0
  struct aspath *aspath;
4855
0
  bool addpath_capable = false;
4856
0
  uint32_t addpath_tx_id = 0;
4857
0
  struct attr *attr = bpi->attr;
4858
4859
  /* Remember current pointer. */
4860
0
  cp = stream_get_endp(s);
4861
4862
  /* Place holder of length. */
4863
0
  stream_putw(s, 0);
4864
4865
  /* Origin attribute. */
4866
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS);
4867
0
  stream_putc(s, BGP_ATTR_ORIGIN);
4868
0
  stream_putc(s, 1);
4869
0
  stream_putc(s, attr->origin);
4870
4871
0
  aspath = attr->aspath;
4872
4873
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4874
0
  stream_putc(s, BGP_ATTR_AS_PATH);
4875
0
  aspath_lenp = stream_get_endp(s);
4876
0
  stream_putw(s, 0);
4877
4878
0
  stream_putw_at(s, aspath_lenp, aspath_put(s, aspath, 1));
4879
4880
  /* Nexthop attribute. */
4881
  /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4882
0
  if (prefix != NULL && prefix->family != AF_INET6) {
4883
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4884
0
    stream_putc(s, BGP_ATTR_NEXT_HOP);
4885
0
    stream_putc(s, 4);
4886
0
    stream_put_ipv4(s, attr->nexthop.s_addr);
4887
0
  }
4888
4889
  /* MED attribute. */
4890
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
4891
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4892
0
    stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4893
0
    stream_putc(s, 4);
4894
0
    stream_putl(s, attr->med);
4895
0
  }
4896
4897
  /* Local preference. */
4898
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
4899
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4900
0
    stream_putc(s, BGP_ATTR_LOCAL_PREF);
4901
0
    stream_putc(s, 4);
4902
0
    stream_putl(s, attr->local_pref);
4903
0
  }
4904
4905
  /* Atomic aggregate. */
4906
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4907
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4908
0
    stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4909
0
    stream_putc(s, 0);
4910
0
  }
4911
4912
  /* Aggregator. */
4913
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4914
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4915
0
    stream_putc(s, BGP_ATTR_AGGREGATOR);
4916
0
    stream_putc(s, 8);
4917
0
    stream_putl(s, attr->aggregator_as);
4918
0
    stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4919
0
  }
4920
4921
  /* Community attribute. */
4922
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
4923
0
    struct community *comm = NULL;
4924
4925
0
    comm = bgp_attr_get_community(attr);
4926
0
    if (comm->size * 4 > 255) {
4927
0
      stream_putc(s,
4928
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4929
0
              | BGP_ATTR_FLAG_EXTLEN);
4930
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4931
0
      stream_putw(s, comm->size * 4);
4932
0
    } else {
4933
0
      stream_putc(s,
4934
0
            BGP_ATTR_FLAG_OPTIONAL
4935
0
              | BGP_ATTR_FLAG_TRANS);
4936
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4937
0
      stream_putc(s, comm->size * 4);
4938
0
    }
4939
0
    stream_put(s, comm->val, comm->size * 4);
4940
0
  }
4941
4942
  /* Large Community attribute. */
4943
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
4944
0
    if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
4945
0
      stream_putc(s,
4946
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4947
0
              | BGP_ATTR_FLAG_EXTLEN);
4948
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4949
0
      stream_putw(s,
4950
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4951
0
    } else {
4952
0
      stream_putc(s,
4953
0
            BGP_ATTR_FLAG_OPTIONAL
4954
0
              | BGP_ATTR_FLAG_TRANS);
4955
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4956
0
      stream_putc(s,
4957
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4958
0
    }
4959
4960
0
    stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4961
0
         lcom_length(bgp_attr_get_lcommunity(attr)));
4962
0
  }
4963
4964
  /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4965
0
  if (prefix != NULL && prefix->family == AF_INET6
4966
0
      && (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
4967
0
    || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)) {
4968
0
    int sizep;
4969
4970
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4971
0
    stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
4972
0
    sizep = stream_get_endp(s);
4973
4974
    /* MP header */
4975
0
    stream_putc(s, 0);      /* Marker: Attribute length. */
4976
0
    stream_putw(s, AFI_IP6);      /* AFI */
4977
0
    stream_putc(s, SAFI_UNICAST); /* SAFI */
4978
4979
    /* Next hop */
4980
0
    stream_putc(s, attr->mp_nexthop_len);
4981
0
    stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
4982
0
    if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
4983
0
      stream_put(s, &attr->mp_nexthop_local,
4984
0
           IPV6_MAX_BYTELEN);
4985
4986
    /* SNPA */
4987
0
    stream_putc(s, 0);
4988
4989
    /* Prefix */
4990
0
    stream_put_prefix_addpath(s, prefix, addpath_capable,
4991
0
            addpath_tx_id);
4992
4993
    /* Set MP attribute length. */
4994
0
    stream_putc_at(s, sizep, (stream_get_endp(s) - sizep) - 1);
4995
0
  }
4996
4997
  /* Prefix SID */
4998
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4999
0
    if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
5000
0
      stream_putc(s,
5001
0
            BGP_ATTR_FLAG_OPTIONAL
5002
0
              | BGP_ATTR_FLAG_TRANS);
5003
0
      stream_putc(s, BGP_ATTR_PREFIX_SID);
5004
0
      stream_putc(s, 10);
5005
0
      stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
5006
0
      stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
5007
0
      stream_putc(s, 0); // reserved
5008
0
      stream_putw(s, 0); // flags
5009
0
      stream_putl(s, attr->label_index);
5010
0
    }
5011
0
  }
5012
5013
  /* OTC */
5014
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
5015
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5016
0
    stream_putc(s, BGP_ATTR_OTC);
5017
0
    stream_putc(s, 4);
5018
0
    stream_putl(s, attr->otc);
5019
0
  }
5020
5021
  /* AIGP */
5022
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
5023
    /* At the moment only AIGP Metric TLV exists for AIGP
5024
     * attribute. If more comes in, do not forget to update
5025
     * attr_len variable to include new ones.
5026
     */
5027
0
    uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
5028
5029
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5030
0
    stream_putc(s, BGP_ATTR_AIGP);
5031
0
    stream_putc(s, attr_len);
5032
0
    stream_put_bgp_aigp_tlv_metric(s, bpi);
5033
0
  }
5034
5035
  /* Return total size of attribute. */
5036
0
  len = stream_get_endp(s) - cp - 2;
5037
0
  stream_putw_at(s, cp, len);
5038
0
}
5039
5040
void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
5041
            const char *discard_attrs, bool set)
5042
0
{
5043
0
  int i, num_attributes;
5044
0
  char **attributes;
5045
0
  afi_t afi;
5046
0
  safi_t safi;
5047
5048
5049
  /* If `no` command specified without arbitrary attributes,
5050
   * then flush all.
5051
   */
5052
0
  if (!discard_attrs) {
5053
0
    for (i = 0; i < BGP_ATTR_MAX; i++)
5054
0
      peer->discard_attrs[i] = false;
5055
0
    goto discard_soft_clear;
5056
0
  }
5057
5058
0
  if (discard_attrs) {
5059
0
    frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
5060
5061
0
    if (set)
5062
0
      for (i = 0; i < BGP_ATTR_MAX; i++)
5063
0
        peer->discard_attrs[i] = false;
5064
5065
0
    for (i = 0; i < num_attributes; i++) {
5066
0
      uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5067
5068
0
      XFREE(MTYPE_TMP, attributes[i]);
5069
5070
      /* Some of the attributes, just can't be ignored. */
5071
0
      if (attr_num == BGP_ATTR_ORIGIN ||
5072
0
          attr_num == BGP_ATTR_AS_PATH ||
5073
0
          attr_num == BGP_ATTR_NEXT_HOP ||
5074
0
          attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5075
0
          attr_num == BGP_ATTR_MP_REACH_NLRI ||
5076
0
          attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5077
0
          attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5078
0
        vty_out(vty,
5079
0
          "%% Can't discard path-attribute %s, ignoring.\n",
5080
0
          lookup_msg(attr_str, attr_num, NULL));
5081
0
        continue;
5082
0
      }
5083
5084
      /* Ignore local-pref, originator-id, cluster-list only
5085
       * for eBGP.
5086
       */
5087
0
      if (peer->sort != BGP_PEER_EBGP &&
5088
0
          (attr_num == BGP_ATTR_LOCAL_PREF ||
5089
0
           attr_num == BGP_ATTR_ORIGINATOR_ID ||
5090
0
           attr_num == BGP_ATTR_CLUSTER_LIST)) {
5091
0
        vty_out(vty,
5092
0
          "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5093
0
          lookup_msg(attr_str, attr_num, NULL));
5094
0
        continue;
5095
0
      }
5096
5097
0
      peer->discard_attrs[attr_num] = set;
5098
0
    }
5099
0
    XFREE(MTYPE_TMP, attributes);
5100
0
  discard_soft_clear:
5101
    /* Configuring path attributes to be discarded will trigger
5102
     * an inbound Route Refresh to ensure that the routing table
5103
     * is up to date.
5104
     */
5105
0
    FOREACH_AFI_SAFI (afi, safi)
5106
0
      peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5107
0
  }
5108
0
}
5109
5110
void bgp_path_attribute_withdraw_vty(struct vty *vty, struct peer *peer,
5111
             const char *withdraw_attrs, bool set)
5112
0
{
5113
0
  int i, num_attributes;
5114
0
  char **attributes;
5115
0
  afi_t afi;
5116
0
  safi_t safi;
5117
5118
  /* If `no` command specified without arbitrary attributes,
5119
   * then flush all.
5120
   */
5121
0
  if (!withdraw_attrs) {
5122
0
    for (i = 0; i < BGP_ATTR_MAX; i++)
5123
0
      peer->withdraw_attrs[i] = false;
5124
0
    goto withdraw_soft_clear;
5125
0
  }
5126
5127
0
  if (withdraw_attrs) {
5128
0
    frrstr_split(withdraw_attrs, " ", &attributes, &num_attributes);
5129
5130
0
    if (set)
5131
0
      for (i = 0; i < BGP_ATTR_MAX; i++)
5132
0
        peer->withdraw_attrs[i] = false;
5133
5134
0
    for (i = 0; i < num_attributes; i++) {
5135
0
      uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5136
5137
0
      XFREE(MTYPE_TMP, attributes[i]);
5138
5139
      /* Some of the attributes, just can't be ignored. */
5140
0
      if (attr_num == BGP_ATTR_ORIGIN ||
5141
0
          attr_num == BGP_ATTR_AS_PATH ||
5142
0
          attr_num == BGP_ATTR_NEXT_HOP ||
5143
0
          attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5144
0
          attr_num == BGP_ATTR_MP_REACH_NLRI ||
5145
0
          attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5146
0
          attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5147
0
        vty_out(vty,
5148
0
          "%% Can't treat-as-withdraw path-attribute %s, ignoring.\n",
5149
0
          lookup_msg(attr_str, attr_num, NULL));
5150
0
        continue;
5151
0
      }
5152
5153
      /* Ignore local-pref, originator-id, cluster-list only
5154
       * for eBGP.
5155
       */
5156
0
      if (peer->sort != BGP_PEER_EBGP &&
5157
0
          (attr_num == BGP_ATTR_LOCAL_PREF ||
5158
0
           attr_num == BGP_ATTR_ORIGINATOR_ID ||
5159
0
           attr_num == BGP_ATTR_CLUSTER_LIST)) {
5160
0
        vty_out(vty,
5161
0
          "%% Can treat-as-withdraw path-attribute %s only for eBGP, ignoring.\n",
5162
0
          lookup_msg(attr_str, attr_num, NULL));
5163
0
        continue;
5164
0
      }
5165
5166
0
      peer->withdraw_attrs[attr_num] = set;
5167
0
    }
5168
0
    XFREE(MTYPE_TMP, attributes);
5169
0
  withdraw_soft_clear:
5170
    /* Configuring path attributes to be treated as withdraw will
5171
     * trigger
5172
     * an inbound Route Refresh to ensure that the routing table
5173
     * is up to date.
5174
     */
5175
0
    FOREACH_AFI_SAFI (afi, safi)
5176
0
      peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5177
0
  }
5178
0
}
5179
5180
enum bgp_attr_parse_ret bgp_attr_ignore(struct peer *peer, uint8_t type)
5181
2
{
5182
2
  bool discard = peer->discard_attrs[type];
5183
2
  bool withdraw = peer->withdraw_attrs[type];
5184
5185
2
  if (bgp_debug_update(peer, NULL, NULL, 1) && (discard || withdraw))
5186
0
    zlog_debug("%pBP: Ignoring attribute %s (%s)", peer,
5187
2
         lookup_msg(attr_str, type, NULL),
5188
2
         withdraw ? "treat-as-withdraw" : "discard");
5189
5190
2
  return withdraw ? BGP_ATTR_PARSE_WITHDRAW : BGP_ATTR_PARSE_PROCEED;
5191
2
}