Coverage Report

Created: 2026-02-21 06:33

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
18
{
87
18
  const struct cluster_list *val = (const struct cluster_list *)p;
88
18
  struct cluster_list *cluster;
89
90
18
  cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list));
91
18
  cluster->length = val->length;
92
93
18
  if (cluster->length) {
94
18
    cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length);
95
18
    memcpy(cluster->list, val->list, val->length);
96
18
  } else
97
0
    cluster->list = NULL;
98
99
18
  cluster->refcnt = 0;
100
101
18
  return cluster;
102
18
}
103
104
/* Cluster list related functions. */
105
static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
106
18
{
107
18
  struct cluster_list tmp = {};
108
18
  struct cluster_list *cluster;
109
110
18
  tmp.length = length;
111
18
  tmp.list = length == 0 ? NULL : pnt;
112
113
18
  cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc);
114
18
  cluster->refcnt++;
115
18
  return cluster;
116
18
}
117
118
bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
119
2
{
120
2
  int i;
121
122
7
  for (i = 0; i < cluster->length / 4; i++)
123
5
    if (cluster->list[i].s_addr == originator.s_addr)
124
0
      return true;
125
2
  return false;
126
2
}
127
128
static unsigned int cluster_hash_key_make(const void *p)
129
36
{
130
36
  const struct cluster_list *cluster = p;
131
132
36
  return jhash(cluster->list, cluster->length, 0);
133
36
}
134
135
static bool cluster_hash_cmp(const void *p1, const void *p2)
136
18
{
137
18
  const struct cluster_list *cluster1 = p1;
138
18
  const struct cluster_list *cluster2 = p2;
139
140
18
  if (cluster1->list == cluster2->list)
141
18
    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
18
{
154
18
  XFREE(MTYPE_CLUSTER_VAL, cluster->list);
155
18
  XFREE(MTYPE_CLUSTER, cluster);
156
18
}
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
18
{
170
18
  if ((*cluster)->refcnt)
171
18
    (*cluster)->refcnt--;
172
173
18
  if ((*cluster)->refcnt == 0) {
174
18
    void *p = hash_release(cluster_hash, *cluster);
175
18
    assert(p == *cluster);
176
18
    cluster_free(*cluster);
177
18
    *cluster = NULL;
178
18
  }
179
18
}
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
7
{
223
7
  struct bgp_attr_encap_subtlv *next;
224
583
  while (p) {
225
576
    next = p->next;
226
576
    p->next = NULL;
227
576
    XFREE(MTYPE_ENCAP_TLV, p);
228
576
    p = next;
229
576
  }
230
7
}
231
232
void bgp_attr_flush_encap(struct attr *attr)
233
166
{
234
166
  if (!attr)
235
0
    return;
236
237
166
  if (attr->encap_subtlvs) {
238
1
    encap_free(attr->encap_subtlvs);
239
1
    attr->encap_subtlvs = NULL;
240
1
  }
241
166
#ifdef ENABLE_BGP_VNC
242
166
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
243
166
    bgp_attr_get_vnc_subtlvs(attr);
244
245
166
  if (vnc_subtlvs) {
246
0
    encap_free(vnc_subtlvs);
247
0
    bgp_attr_set_vnc_subtlvs(attr, NULL);
248
0
  }
249
166
#endif
250
166
}
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
6
{
263
6
  const struct bgp_attr_encap_subtlv *p;
264
6
  const struct bgp_attr_encap_subtlv *q;
265
266
6
  if (h1 == h2)
267
6
    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
6
{
300
  /* Encap structure is already allocated.  */
301
6
  return p;
302
6
}
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
6
{
314
6
  struct bgp_attr_encap_subtlv *find;
315
6
  struct hash *hash = encap_hash;
316
6
#ifdef ENABLE_BGP_VNC
317
6
  if (type == VNC_SUBTLV_TYPE)
318
0
    hash = vnc_hash;
319
6
#endif
320
321
6
  find = hash_get(hash, encap, encap_hash_alloc);
322
6
  if (find != encap)
323
0
    encap_free(encap);
324
6
  find->refcnt++;
325
326
6
  return find;
327
6
}
328
329
static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
330
         encap_subtlv_type type)
331
6
{
332
6
  struct bgp_attr_encap_subtlv *encap = *encapp;
333
6
  if (encap->refcnt)
334
6
    encap->refcnt--;
335
336
6
  if (encap->refcnt == 0) {
337
6
    struct hash *hash = encap_hash;
338
6
#ifdef ENABLE_BGP_VNC
339
6
    if (type == VNC_SUBTLV_TYPE)
340
0
      hash = vnc_hash;
341
6
#endif
342
6
    hash_release(hash, encap);
343
6
    encap_free(encap);
344
6
    *encapp = NULL;
345
6
  }
346
6
}
347
348
static unsigned int encap_hash_key_make(const void *p)
349
12
{
350
12
  const struct bgp_attr_encap_subtlv *encap = p;
351
352
12
  return jhash(encap->value, encap->length, 0);
353
12
}
354
355
static bool encap_hash_cmp(const void *p1, const void *p2)
356
6
{
357
6
  return encap_same((const struct bgp_attr_encap_subtlv *)p1,
358
6
        (const struct bgp_attr_encap_subtlv *)p2);
359
6
}
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
161
{
397
161
  XFREE(MTYPE_TRANSIT_VAL, transit->val);
398
161
  XFREE(MTYPE_TRANSIT, transit);
399
161
}
400
401
static void *transit_hash_alloc(void *p)
402
147
{
403
  /* Transit structure is already allocated.  */
404
147
  return p;
405
147
}
406
407
static struct transit *transit_intern(struct transit *transit)
408
147
{
409
147
  struct transit *find;
410
411
147
  find = hash_get(transit_hash, transit, transit_hash_alloc);
412
147
  if (find != transit)
413
0
    transit_free(transit);
414
147
  find->refcnt++;
415
416
147
  return find;
417
147
}
418
419
static void transit_unintern(struct transit **transit)
420
147
{
421
147
  if ((*transit)->refcnt)
422
147
    (*transit)->refcnt--;
423
424
147
  if ((*transit)->refcnt == 0) {
425
147
    hash_release(transit_hash, *transit);
426
147
    transit_free(*transit);
427
147
    *transit = NULL;
428
147
  }
429
147
}
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
10
{
549
10
  XFREE(MTYPE_BGP_SRV6_L3VPN, l3vpn);
550
10
}
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
10
{
566
10
  struct bgp_attr_srv6_l3vpn *l3vpn = *l3vpnp;
567
568
10
  if (l3vpn->refcnt)
569
6
    l3vpn->refcnt--;
570
571
10
  if (l3vpn->refcnt == 0) {
572
10
    hash_release(srv6_l3vpn_hash, l3vpn);
573
10
    srv6_l3vpn_free(l3vpn);
574
10
    *l3vpnp = NULL;
575
10
  }
576
10
}
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
16
{
615
16
  const struct bgp_attr_srv6_l3vpn *l3vpn = p;
616
16
  uint32_t key = 0;
617
618
16
  key = jhash(&l3vpn->sid, 16, key);
619
16
  key = jhash_1word(l3vpn->sid_flags, key);
620
16
  key = jhash_1word(l3vpn->endpoint_behavior, key);
621
16
  key = jhash_1word(l3vpn->loc_block_len, key);
622
16
  key = jhash_1word(l3vpn->loc_node_len, key);
623
16
  key = jhash_1word(l3vpn->func_len, key);
624
16
  key = jhash_1word(l3vpn->arg_len, key);
625
16
  key = jhash_1word(l3vpn->transposition_len, key);
626
16
  key = jhash_1word(l3vpn->transposition_offset, key);
627
16
  return key;
628
16
}
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
294
{
705
294
  const struct transit *transit = p;
706
707
294
  return jhash(transit->val, transit->length, 0);
708
294
}
709
710
static bool transit_hash_cmp(const void *p1, const void *p2)
711
147
{
712
147
  const struct transit *transit1 = p1;
713
147
  const struct transit *transit2 = p2;
714
715
147
  return (transit1->length == transit2->length
716
147
    && memcmp(transit1->val, transit2->val, transit1->length) == 0);
717
147
}
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
623
{
1188
623
  struct ecommunity *ecomm = NULL;
1189
623
  struct ecommunity *ipv6_ecomm = NULL;
1190
623
  struct cluster_list *cluster;
1191
623
  struct lcommunity *lcomm = NULL;
1192
623
  struct community *comm = NULL;
1193
1194
  /* aspath refcount shoud be decrement. */
1195
623
  aspath_unintern(&attr->aspath);
1196
623
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
1197
1198
623
  comm = bgp_attr_get_community(attr);
1199
623
  community_unintern(&comm);
1200
623
  bgp_attr_set_community(attr, NULL);
1201
1202
623
  ecomm = bgp_attr_get_ecommunity(attr);
1203
623
  ecommunity_unintern(&ecomm);
1204
623
  bgp_attr_set_ecommunity(attr, NULL);
1205
1206
623
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1207
623
  ecommunity_unintern(&ipv6_ecomm);
1208
623
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1209
1210
623
  lcomm = bgp_attr_get_lcommunity(attr);
1211
623
  lcommunity_unintern(&lcomm);
1212
623
  bgp_attr_set_lcommunity(attr, NULL);
1213
1214
623
  cluster = bgp_attr_get_cluster(attr);
1215
623
  if (cluster) {
1216
18
    cluster_unintern(&cluster);
1217
18
    bgp_attr_set_cluster(attr, cluster);
1218
18
  }
1219
623
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
1220
1221
623
  struct transit *transit = bgp_attr_get_transit(attr);
1222
1223
623
  if (transit) {
1224
147
    transit_unintern(&transit);
1225
147
    bgp_attr_set_transit(attr, transit);
1226
147
  }
1227
1228
623
  if (attr->encap_subtlvs)
1229
6
    encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
1230
1231
623
#ifdef ENABLE_BGP_VNC
1232
623
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1233
623
    bgp_attr_get_vnc_subtlvs(attr);
1234
1235
623
  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
623
#endif
1240
1241
623
  if (attr->srv6_l3vpn)
1242
10
    srv6_l3vpn_unintern(&attr->srv6_l3vpn);
1243
1244
623
  if (attr->srv6_vpn)
1245
0
    srv6_vpn_unintern(&attr->srv6_vpn);
1246
623
}
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.34k
{
1273
2.34k
  struct ecommunity *ecomm;
1274
2.34k
  struct ecommunity *ipv6_ecomm;
1275
2.34k
  struct cluster_list *cluster;
1276
2.34k
  struct lcommunity *lcomm;
1277
2.34k
  struct community *comm;
1278
1279
2.34k
  if (attr->aspath && !attr->aspath->refcnt) {
1280
0
    aspath_free(attr->aspath);
1281
0
    attr->aspath = NULL;
1282
0
  }
1283
2.34k
  comm = bgp_attr_get_community(attr);
1284
2.34k
  if (comm && !comm->refcnt)
1285
271
    community_free(&comm);
1286
2.34k
  bgp_attr_set_community(attr, NULL);
1287
1288
2.34k
  ecomm = bgp_attr_get_ecommunity(attr);
1289
2.34k
  if (ecomm && !ecomm->refcnt)
1290
0
    ecommunity_free(&ecomm);
1291
2.34k
  bgp_attr_set_ecommunity(attr, NULL);
1292
1293
2.34k
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1294
2.34k
  if (ipv6_ecomm && !ipv6_ecomm->refcnt)
1295
0
    ecommunity_free(&ipv6_ecomm);
1296
2.34k
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1297
1298
2.34k
  lcomm = bgp_attr_get_lcommunity(attr);
1299
2.34k
  if (lcomm && !lcomm->refcnt)
1300
0
    lcommunity_free(&lcomm);
1301
2.34k
  bgp_attr_set_lcommunity(attr, NULL);
1302
1303
2.34k
  cluster = bgp_attr_get_cluster(attr);
1304
2.34k
  if (cluster && !cluster->refcnt) {
1305
0
    cluster_free(cluster);
1306
0
    bgp_attr_set_cluster(attr, NULL);
1307
0
  }
1308
1309
2.34k
  struct transit *transit = bgp_attr_get_transit(attr);
1310
1311
2.34k
  if (transit && !transit->refcnt) {
1312
0
    transit_free(transit);
1313
0
    bgp_attr_set_transit(attr, NULL);
1314
0
  }
1315
2.34k
  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.34k
  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.34k
  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.34k
#ifdef ENABLE_BGP_VNC
1328
2.34k
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1329
2.34k
    bgp_attr_get_vnc_subtlvs(attr);
1330
1331
2.34k
  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.34k
#endif
1336
2.34k
}
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
164
{
1347
164
  struct peer *const peer = args->peer;
1348
164
  struct attr *const attr = args->attr;
1349
164
  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
164
  uint8_t *notify_datap = (length > 0 ? args->startp : NULL);
1355
1356
164
  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
164
  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
164
  stream_set_getp(BGP_INPUT(peer),
1375
164
      (args->startp - STREAM_DATA(BGP_INPUT(peer)))
1376
164
        + args->total);
1377
1378
164
  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
4
  case BGP_ATTR_AS4_AGGREGATOR:
1385
9
  case BGP_ATTR_AGGREGATOR:
1386
22
  case BGP_ATTR_ATOMIC_AGGREGATE:
1387
22
    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
25
  case BGP_ATTR_AS_PATH:
1394
37
  case BGP_ATTR_AS4_PATH:
1395
41
  case BGP_ATTR_NEXT_HOP:
1396
50
  case BGP_ATTR_MULTI_EXIT_DISC:
1397
52
  case BGP_ATTR_LOCAL_PREF:
1398
53
  case BGP_ATTR_COMMUNITIES:
1399
54
  case BGP_ATTR_EXT_COMMUNITIES:
1400
57
  case BGP_ATTR_IPV6_EXT_COMMUNITIES:
1401
60
  case BGP_ATTR_LARGE_COMMUNITIES:
1402
62
  case BGP_ATTR_ORIGINATOR_ID:
1403
62
  case BGP_ATTR_CLUSTER_LIST:
1404
64
  case BGP_ATTR_PMSI_TUNNEL:
1405
70
  case BGP_ATTR_ENCAP:
1406
71
  case BGP_ATTR_OTC:
1407
71
    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
164
  }
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
71
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
1420
42
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1421
36
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
1422
16
    return BGP_ATTR_PARSE_WITHDRAW;
1423
1424
  /* default to reset */
1425
55
  return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1426
71
}
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
11
{
1438
11
  uint8_t seen = 0, i;
1439
11
  uint8_t real_flags = args->flags;
1440
11
  const uint8_t attr_code = args->type;
1441
1442
11
  desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1443
11
  real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1444
44
  for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1445
33
    if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1446
33
        != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
1447
15
      flog_err(EC_BGP_ATTR_FLAG,
1448
15
         "%s attribute must%s be flagged as \"%s\"",
1449
15
         lookup_msg(attr_str, attr_code, NULL),
1450
15
         CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1451
15
           ? ""
1452
15
           : " not",
1453
15
         attr_flag_str[i].str);
1454
15
      seen = 1;
1455
15
    }
1456
11
  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
11
}
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.79k
{
1498
1.79k
  uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
1499
1.79k
  const uint8_t flags = args->flags;
1500
1.79k
  const uint8_t attr_code = args->type;
1501
1502
  /* there may be attributes we don't know about */
1503
1.79k
  if (attr_code > attr_flags_values_max)
1504
363
    return false;
1505
1.42k
  if (attr_flags_values[attr_code] == 0)
1506
99
    return false;
1507
1508
  /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1509
   * to
1510
   * 1."
1511
   */
1512
1.33k
  if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
1513
675
      && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
1514
33
    flog_err(
1515
33
      EC_BGP_ATTR_FLAG,
1516
33
      "%s well-known attributes must have transitive flag set (%x)",
1517
33
      lookup_msg(attr_str, attr_code, NULL), flags);
1518
33
    return true;
1519
33
  }
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.29k
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
1526
204
    if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) {
1527
0
      flog_err(EC_BGP_ATTR_FLAG,
1528
0
         "%s well-known attribute must NOT have the partial flag set (%x)",
1529
0
         lookup_msg(attr_str, attr_code, NULL), flags);
1530
0
      return true;
1531
0
    }
1532
204
    if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1533
204
        && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) {
1534
2
      flog_err(EC_BGP_ATTR_FLAG,
1535
2
         "%s optional + transitive attribute must NOT have the partial flag set (%x)",
1536
2
         lookup_msg(attr_str, attr_code, NULL), flags);
1537
2
      return true;
1538
2
    }
1539
204
  }
1540
1541
  /* Optional transitive attributes may go through speakers that don't
1542
   * reocgnise them and set the Partial bit.
1543
   */
1544
1.29k
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1545
653
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
1546
262
    SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
1547
1548
1.29k
  if ((flags & ~mask) == attr_flags_values[attr_code])
1549
1.28k
    return false;
1550
1551
11
  bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
1552
11
  return true;
1553
1.29k
}
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
275
{
1559
275
  struct peer *const peer = args->peer;
1560
275
  struct attr *const attr = args->attr;
1561
275
  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
275
  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
272
  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
272
  if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
1582
95
      && (attr->origin != BGP_ORIGIN_INCOMPLETE)) {
1583
1
    flog_err(EC_BGP_ATTR_ORIGIN,
1584
1
       "Origin attribute value is invalid %d", attr->origin);
1585
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
1586
1
            args->total);
1587
1
  }
1588
1589
  /* Set oring attribute flag. */
1590
271
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1591
1592
271
  return 0;
1593
272
}
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
293
{
1599
293
  struct attr *const attr = args->attr;
1600
293
  struct peer *const peer = args->peer;
1601
293
  const bgp_size_t length = args->length;
1602
293
  enum asnotation_mode asnotation;
1603
1604
293
  asnotation = bgp_get_asnotation(
1605
293
    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
293
  attr->aspath =
1611
293
    aspath_parse(peer->curr, length,
1612
293
           CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
1613
293
             CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
1614
293
           asnotation);
1615
1616
  /* In case of IBGP, length will be zero. */
1617
293
  if (!attr->aspath) {
1618
7
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1619
7
       "Malformed AS path from %s, length is %d", peer->host,
1620
7
       length);
1621
7
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1622
7
            0);
1623
7
  }
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
286
  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
286
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1641
1642
286
  return BGP_ATTR_PARSE_PROCEED;
1643
286
}
1644
1645
static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
1646
                 struct attr *const attr)
1647
270
{
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
270
  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
270
  (void)peer_sort(peer);
1664
1665
  /* Confederation sanity check. */
1666
270
  if ((peer->sort == BGP_PEER_CONFED
1667
0
       && !aspath_left_confed_check(attr->aspath))
1668
270
      || (peer->sort == BGP_PEER_EBGP
1669
270
    && 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
270
  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
270
  if (peer->sort == BGP_PEER_EBGP && aspath_check_as_zero(attr->aspath)) {
1688
0
    flog_err(
1689
0
      EC_BGP_ATTR_MAL_AS_PATH,
1690
0
      "Malformed AS path, AS number is 0 in the path from %s",
1691
0
      peer->host);
1692
0
    return BGP_ATTR_PARSE_WITHDRAW;
1693
0
  }
1694
1695
  /* local-as prepend */
1696
270
  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
270
  return BGP_ATTR_PARSE_PROCEED;
1705
270
}
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
33
{
1712
33
  struct peer *const peer = args->peer;
1713
33
  struct attr *const attr = args->attr;
1714
33
  const bgp_size_t length = args->length;
1715
33
  enum asnotation_mode asnotation;
1716
1717
33
  asnotation = bgp_get_asnotation(peer->bgp);
1718
1719
33
  *as4_path = aspath_parse(peer->curr, length, 1, asnotation);
1720
1721
  /* In case of IBGP, length will be zero. */
1722
33
  if (!*as4_path) {
1723
12
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1724
12
       "Malformed AS4 path from %s, length is %d", peer->host,
1725
12
       length);
1726
12
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1727
12
            0);
1728
12
  }
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
21
  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
21
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1745
1746
21
  return BGP_ATTR_PARSE_PROCEED;
1747
21
}
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
61
{
1779
61
  struct peer *const peer = args->peer;
1780
61
  struct attr *const attr = args->attr;
1781
61
  const bgp_size_t length = args->length;
1782
1783
  /* Check nexthop attribute length. */
1784
61
  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
60
  attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
1793
60
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1794
1795
60
  return BGP_ATTR_PARSE_PROCEED;
1796
61
}
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
4
    flog_err(EC_BGP_ATTR_LEN,
1808
4
       "MED attribute length isn't four [%d]", length);
1809
1810
4
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1811
4
            args->total);
1812
4
  }
1813
1814
3
  attr->med = stream_getl(peer->curr);
1815
1816
3
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1817
1818
3
  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
5
{
1825
5
  struct peer *const peer = args->peer;
1826
5
  struct attr *const attr = args->attr;
1827
5
  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
5
  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
5
  if (peer->sort == BGP_PEER_EBGP) {
1845
5
    STREAM_FORWARD_GETP(peer->curr, length);
1846
5
    return BGP_ATTR_PARSE_PROCEED;
1847
5
  }
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
6
{
1864
6
  struct peer *const peer = args->peer;
1865
6
  struct attr *const attr = args->attr;
1866
6
  const bgp_size_t length = args->length;
1867
1868
  /* Length check. */
1869
6
  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
3
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1878
0
    goto atomic_ignore;
1879
1880
  /* Set atomic aggregate flag. */
1881
3
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1882
1883
3
  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
3
}
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
3
{
1956
3
  struct peer *const peer = args->peer;
1957
3
  struct attr *const attr = args->attr;
1958
3
  const bgp_size_t length = args->length;
1959
3
  as_t aggregator_as;
1960
1961
3
  if (length != 8) {
1962
3
    flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1963
3
       length);
1964
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1965
3
            0);
1966
3
  }
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
270
{
2008
270
  int ignore_as4_path = 0;
2009
270
  struct aspath *newpath;
2010
2011
270
  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
270
  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
270
    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
270
    return BGP_ATTR_PARSE_PROCEED;
2041
270
  }
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
27
{
2108
27
  struct peer *const peer = args->peer;
2109
27
  struct attr *const attr = args->attr;
2110
27
  const bgp_size_t length = args->length;
2111
2112
27
  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
27
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2119
0
    goto community_ignore;
2120
2121
27
  bgp_attr_set_community(
2122
27
    attr,
2123
27
    community_parse((uint32_t *)stream_pnt(peer->curr), length));
2124
2125
  /* XXX: fix community_parse to use stream API and remove this */
2126
27
  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
27
  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
27
  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
27
}
2142
2143
/* Originator ID attribute. */
2144
static enum bgp_attr_parse_ret
2145
bgp_attr_originator_id(struct bgp_attr_parser_args *args)
2146
10
{
2147
10
  struct peer *const peer = args->peer;
2148
10
  struct attr *const attr = args->attr;
2149
10
  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
10
  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
10
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2165
0
    goto originator_id_ignore;
2166
2167
10
  attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
2168
2169
10
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2170
2171
10
  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
10
}
2178
2179
/* Cluster list attribute. */
2180
static enum bgp_attr_parse_ret
2181
bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
2182
18
{
2183
18
  struct peer *const peer = args->peer;
2184
18
  struct attr *const attr = args->attr;
2185
18
  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
18
  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
18
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2200
0
    goto cluster_list_ignore;
2201
2202
18
  bgp_attr_set_cluster(
2203
18
    attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2204
18
            length));
2205
2206
  /* XXX: Fix cluster_parse to use stream API and then remove this */
2207
18
  stream_forward_getp(peer->curr, length);
2208
2209
18
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
2210
2211
18
  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
18
}
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
341
{
2223
341
  iana_afi_t pkt_afi;
2224
341
  afi_t afi;
2225
341
  iana_safi_t pkt_safi;
2226
341
  safi_t safi;
2227
341
  bgp_size_t nlri_len;
2228
341
  size_t start;
2229
341
  struct stream *s;
2230
341
  struct peer *const peer = args->peer;
2231
341
  struct attr *const attr = args->attr;
2232
341
  const bgp_size_t length = args->length;
2233
2234
  /* Set end of packet. */
2235
341
  s = BGP_INPUT(peer);
2236
341
  start = stream_get_getp(s);
2237
2238
/* safe to read statically sized header? */
2239
341
#define BGP_MP_REACH_MIN_SIZE 5
2240
1.02k
#define LEN_LEFT  (length - (stream_get_getp(s) - start))
2241
341
  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
341
  pkt_afi = stream_getw(s);
2249
341
  pkt_safi = stream_getc(s);
2250
2251
  /* Convert AFI, SAFI to internal values, check. */
2252
341
  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
341
  attr->mp_nexthop_len = stream_getc(s);
2267
2268
341
  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
341
  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
15
  case BGP_ATTR_NHLEN_VPNV4:
2285
15
    stream_getl(s); /* RD high */
2286
15
    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
72
  case BGP_ATTR_NHLEN_IPV4:
2296
72
    stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2297
    /* Probably needed for RFC 2283 */
2298
72
    if (attr->nexthop.s_addr == INADDR_ANY)
2299
65
      memcpy(&attr->nexthop.s_addr,
2300
65
             &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2301
72
    break;
2302
268
  case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2303
268
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2304
268
    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
268
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2309
268
    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
268
    break;
2318
268
  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
341
  }
2361
2362
340
  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
340
  {
2369
340
    uint8_t val;
2370
340
    if ((val = stream_getc(s)))
2371
224
      flog_warn(
2372
340
        EC_BGP_DEFUNCT_SNPA_LEN,
2373
340
        "%s sent non-zero value, %u, for defunct SNPA-length field",
2374
340
        peer->host, val);
2375
340
  }
2376
2377
  /* must have nrli_len, what is left of the attribute */
2378
340
  nlri_len = LEN_LEFT;
2379
340
  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
340
  if (!nlri_len) {
2386
46
    zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2387
46
        __func__, peer->host);
2388
2389
46
    mp_update->afi = afi;
2390
46
    mp_update->safi = safi;
2391
46
    return BGP_ATTR_PARSE_EOR;
2392
46
  }
2393
2394
294
  mp_update->afi = afi;
2395
294
  mp_update->safi = safi;
2396
294
  mp_update->nlri = stream_pnt(s);
2397
294
  mp_update->length = nlri_len;
2398
2399
294
  stream_forward_getp(s, nlri_len);
2400
2401
294
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2402
2403
294
  return BGP_ATTR_PARSE_PROCEED;
2404
340
#undef LEN_LEFT
2405
340
}
2406
2407
/* Multiprotocol unreachable parse */
2408
int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2409
       struct bgp_nlri *mp_withdraw)
2410
11
{
2411
11
  struct stream *s;
2412
11
  iana_afi_t pkt_afi;
2413
11
  afi_t afi;
2414
11
  iana_safi_t pkt_safi;
2415
11
  safi_t safi;
2416
11
  uint16_t withdraw_len;
2417
11
  struct peer *const peer = args->peer;
2418
11
  struct attr *const attr = args->attr;
2419
11
  const bgp_size_t length = args->length;
2420
2421
11
  s = peer->curr;
2422
2423
18
#define BGP_MP_UNREACH_MIN_SIZE 3
2424
11
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2425
2
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2426
2427
9
  pkt_afi = stream_getw(s);
2428
9
  pkt_safi = stream_getc(s);
2429
2430
  /* Convert AFI, SAFI to internal values, check. */
2431
9
  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
7
  withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
2445
2446
7
  mp_withdraw->afi = afi;
2447
7
  mp_withdraw->safi = safi;
2448
7
  mp_withdraw->nlri = stream_pnt(s);
2449
7
  mp_withdraw->length = withdraw_len;
2450
2451
7
  stream_forward_getp(s, withdraw_len);
2452
2453
7
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
2454
2455
7
  return BGP_ATTR_PARSE_PROCEED;
2456
9
}
2457
2458
/* Large Community attribute. */
2459
static enum bgp_attr_parse_ret
2460
bgp_attr_large_community(struct bgp_attr_parser_args *args)
2461
14
{
2462
14
  struct peer *const peer = args->peer;
2463
14
  struct attr *const attr = args->attr;
2464
14
  const bgp_size_t length = args->length;
2465
2466
  /*
2467
   * Large community follows new attribute format.
2468
   */
2469
14
  if (length == 0) {
2470
1
    bgp_attr_set_lcommunity(attr, NULL);
2471
    /* Empty extcomm doesn't seem to be invalid per se */
2472
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2473
1
            args->total);
2474
1
  }
2475
2476
13
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2477
0
    goto large_community_ignore;
2478
2479
13
  bgp_attr_set_lcommunity(
2480
13
    attr, lcommunity_parse(stream_pnt(peer->curr), length));
2481
  /* XXX: fix ecommunity_parse to use stream API */
2482
13
  stream_forward_getp(peer->curr, length);
2483
2484
13
  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
11
  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
13
}
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
8
    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
10
    attr->es_flags |= ATTR_ES_PROXY_ADVERT;
2550
2551
  /* Extract the Rmac, if any */
2552
109
  if (bgp_attr_rmac(attr, &attr->rmac)) {
2553
5
    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
5
           &attr->rmac);
2557
5
  }
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
28
{
2574
28
  struct peer *const peer = args->peer;
2575
28
  struct attr *const attr = args->attr;
2576
28
  const bgp_size_t length = args->length;
2577
28
  struct ecommunity *ipv6_ecomm = NULL;
2578
2579
28
  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
28
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2586
0
    goto ipv6_ext_community_ignore;
2587
2588
28
  ipv6_ecomm = ecommunity_parse_ipv6(
2589
28
    stream_pnt(peer->curr), length,
2590
28
    CHECK_FLAG(peer->flags,
2591
28
         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2592
28
  bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2593
2594
  /* XXX: fix ecommunity_parse to use stream API */
2595
28
  stream_forward_getp(peer->curr, length);
2596
2597
28
  if (!ipv6_ecomm)
2598
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2599
3
            args->total);
2600
2601
25
  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
28
}
2608
2609
/* Parse Tunnel Encap attribute in an UPDATE */
2610
static int bgp_attr_encap(struct bgp_attr_parser_args *args)
2611
7
{
2612
7
  uint16_t tunneltype = 0;
2613
7
  struct peer *const peer = args->peer;
2614
7
  struct attr *const attr = args->attr;
2615
7
  bgp_size_t length = args->length;
2616
7
  uint8_t type = args->type;
2617
7
  uint8_t flag = args->flags;
2618
2619
7
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2620
7
      || !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
7
  if (BGP_ATTR_ENCAP == type) {
2628
    /* read outer TLV type and length */
2629
7
    uint16_t tlv_length;
2630
2631
7
    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
7
    tunneltype = stream_getw(BGP_INPUT(peer));
2639
7
    tlv_length = stream_getw(BGP_INPUT(peer));
2640
7
    length -= 4;
2641
2642
7
    if (tlv_length != length) {
2643
7
      zlog_info("%s: tlv_length(%d) != length(%d)",
2644
7
          __func__, tlv_length, length);
2645
7
    }
2646
7
  }
2647
2648
583
  while (length >= 4) {
2649
582
    uint16_t subtype = 0;
2650
582
    uint16_t sublength = 0;
2651
582
    struct bgp_attr_encap_subtlv *tlv;
2652
2653
582
    if (BGP_ATTR_ENCAP == type) {
2654
582
      subtype = stream_getc(BGP_INPUT(peer));
2655
582
      sublength = stream_getc(BGP_INPUT(peer));
2656
582
      length -= 2;
2657
582
#ifdef ENABLE_BGP_VNC
2658
582
    } 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
582
    if (sublength > length) {
2666
6
      zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2667
6
         sublength, length);
2668
6
      return bgp_attr_malformed(args,
2669
6
              BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2670
6
              args->total);
2671
6
    }
2672
2673
    /* alloc and copy sub-tlv */
2674
    /* TBD make sure these are freed when attributes are released */
2675
576
    tlv = XCALLOC(MTYPE_ENCAP_TLV,
2676
576
            sizeof(struct bgp_attr_encap_subtlv) + sublength);
2677
576
    tlv->type = subtype;
2678
576
    tlv->length = sublength;
2679
576
    stream_get(tlv->value, peer->curr, sublength);
2680
576
    length -= sublength;
2681
2682
    /* attach tlv to encap chain */
2683
576
    if (BGP_ATTR_ENCAP == type) {
2684
576
      struct bgp_attr_encap_subtlv *stlv_last;
2685
576
      for (stlv_last = attr->encap_subtlvs;
2686
36.8k
           stlv_last && stlv_last->next;
2687
36.3k
           stlv_last = stlv_last->next)
2688
36.3k
        ;
2689
576
      if (stlv_last) {
2690
569
        stlv_last->next = tlv;
2691
569
      } else {
2692
7
        attr->encap_subtlvs = tlv;
2693
7
      }
2694
576
#ifdef ENABLE_BGP_VNC
2695
576
    } 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
576
  }
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
9
{
2734
9
  struct peer *const peer = args->peer;
2735
9
  struct attr *const attr = args->attr;
2736
9
  uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2737
9
    transposition_len, transposition_offset;
2738
9
  uint16_t length;
2739
9
  size_t headersz = sizeof(type) + sizeof(length);
2740
2741
9
  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
9
  type = stream_getc(peer->curr);
2751
9
  length = stream_getw(peer->curr);
2752
2753
9
  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
9
  if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2763
4
    flog_err(
2764
4
      EC_BGP_ATTR_LEN,
2765
4
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2766
4
      BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2767
4
      length);
2768
4
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2769
4
            args->total);
2770
4
  }
2771
2772
5
  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
3
  else {
2810
3
    if (bgp_debug_update(peer, NULL, NULL, 1))
2811
0
      zlog_debug(
2812
3
        "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2813
3
        peer->host, type);
2814
2815
3
    stream_forward_getp(peer->curr, length);
2816
3
  }
2817
2818
5
  return BGP_ATTR_PARSE_PROCEED;
2819
5
}
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
22
{
2827
22
  struct peer *const peer = args->peer;
2828
22
  struct attr *const attr = args->attr;
2829
22
  struct in6_addr ipv6_sid;
2830
22
  uint8_t type, sid_flags;
2831
22
  uint16_t length, endpoint_behavior;
2832
22
  size_t headersz = sizeof(type) + sizeof(length);
2833
22
  enum bgp_attr_parse_ret err;
2834
2835
22
  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
22
  type = stream_getc(peer->curr);
2845
22
  length = stream_getw(peer->curr);
2846
2847
22
  if (STREAM_READABLE(peer->curr) < length) {
2848
5
    flog_err(
2849
5
      EC_BGP_ATTR_LEN,
2850
5
      "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2851
5
      length, STREAM_READABLE(peer->curr));
2852
5
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2853
5
            args->total);
2854
5
  }
2855
2856
17
  if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
2857
11
    if (STREAM_READABLE(peer->curr) <
2858
11
        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
11
    stream_getc(peer->curr);
2869
11
    stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2870
11
    sid_flags = stream_getc(peer->curr);
2871
11
    endpoint_behavior = stream_getw(peer->curr);
2872
11
    stream_getc(peer->curr);
2873
2874
    /* Log SRv6 Service Sub-TLV */
2875
11
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
2876
0
      zlog_debug(
2877
11
        "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2878
11
        __func__, &ipv6_sid, sid_flags,
2879
11
        endpoint_behavior);
2880
2881
    /* Configure from Info */
2882
11
    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
10
    attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2889
10
             sizeof(struct bgp_attr_srv6_l3vpn));
2890
10
    sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
2891
10
    attr->srv6_l3vpn->sid_flags = sid_flags;
2892
10
    attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
2893
10
    attr->srv6_l3vpn->loc_block_len = 0;
2894
10
    attr->srv6_l3vpn->loc_node_len = 0;
2895
10
    attr->srv6_l3vpn->func_len = 0;
2896
10
    attr->srv6_l3vpn->arg_len = 0;
2897
10
    attr->srv6_l3vpn->transposition_len = 0;
2898
10
    attr->srv6_l3vpn->transposition_offset = 0;
2899
2900
    // Sub-Sub-TLV found
2901
10
    if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2902
9
      err = bgp_attr_srv6_service_data(args);
2903
2904
9
      if (err != BGP_ATTR_PARSE_PROCEED)
2905
4
        return err;
2906
9
    }
2907
2908
6
    attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
2909
6
  }
2910
2911
  /* Placeholder code for unsupported type */
2912
6
  else {
2913
6
    if (bgp_debug_update(peer, NULL, NULL, 1))
2914
0
      zlog_debug(
2915
6
        "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2916
6
        peer->host, type);
2917
2918
6
    stream_forward_getp(peer->curr, length);
2919
6
  }
2920
2921
12
  return BGP_ATTR_PARSE_PROCEED;
2922
17
}
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
1
    if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
2979
1
      flog_err(EC_BGP_ATTR_LEN,
2980
1
         "Prefix SID IPv6 length is %hu instead of %u",
2981
1
         length, BGP_PREFIX_SID_IPV6_LENGTH);
2982
1
      return bgp_attr_malformed(args,
2983
1
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2984
1
              args->total);
2985
1
    }
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
227
  } 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
168
    for (int i = 0; i < srgb_count; i++) {
3037
166
      stream_get(&srgb_base, peer->curr, 3);
3038
166
      stream_get(&srgb_range, peer->curr, 3);
3039
166
    }
3040
223
  } else if (type == BGP_PREFIX_SID_VPN_SID) {
3041
1
    if (length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
3042
1
      flog_err(EC_BGP_ATTR_LEN,
3043
1
         "Prefix SID VPN SID length is %hu instead of %u",
3044
1
         length, BGP_PREFIX_SID_VPN_SID_LENGTH);
3045
1
      return bgp_attr_malformed(args,
3046
1
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3047
1
              args->total);
3048
1
    }
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
22
    if (STREAM_READABLE(peer->curr) < 1) {
3077
0
      flog_err(
3078
0
        EC_BGP_ATTR_LEN,
3079
0
        "Prefix SID SRV6 L3 Service not enough data left, it must be at least 1 byte");
3080
0
      return bgp_attr_malformed(
3081
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3082
0
        args->total);
3083
0
    }
3084
    /* ignore reserved */
3085
22
    stream_getc(peer->curr);
3086
3087
22
    return bgp_attr_srv6_service(args);
3088
22
  }
3089
  /* Placeholder code for Unsupported TLV */
3090
200
  else {
3091
200
    if (bgp_debug_update(peer, NULL, NULL, 1))
3092
0
      zlog_debug(
3093
200
        "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3094
200
        peer->host, type);
3095
3096
200
    stream_forward_getp(peer->curr, length);
3097
200
  }
3098
3099
203
  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
38
{
3107
38
  struct peer *const peer = args->peer;
3108
38
  struct attr *const attr = args->attr;
3109
38
  enum bgp_attr_parse_ret ret;
3110
3111
38
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3112
3113
38
  uint8_t type;
3114
38
  uint16_t length;
3115
38
  size_t headersz = sizeof(type) + sizeof(length);
3116
38
  size_t psid_parsed_length = 0;
3117
3118
250
  while (STREAM_READABLE(peer->curr) > 0
3119
250
         && psid_parsed_length < args->length) {
3120
3121
248
    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
247
    type = stream_getc(peer->curr);
3132
247
    length = stream_getw(peer->curr);
3133
3134
247
    if (STREAM_READABLE(peer->curr) < length) {
3135
16
      flog_err(
3136
16
        EC_BGP_ATTR_LEN,
3137
16
        "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3138
16
        length, STREAM_READABLE(peer->curr));
3139
16
      return bgp_attr_malformed(args,
3140
16
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3141
16
              args->total);
3142
16
    }
3143
3144
231
    ret = bgp_attr_psid_sub(type, length, args);
3145
3146
231
    if (ret != BGP_ATTR_PARSE_PROCEED)
3147
16
      return ret;
3148
3149
215
    psid_parsed_length += length + headersz;
3150
3151
215
    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
215
  }
3161
3162
2
  return BGP_ATTR_PARSE_PROCEED;
3163
38
}
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
1
{
3218
1
  struct peer *const peer = args->peer;
3219
1
  struct attr *const attr = args->attr;
3220
1
  const bgp_size_t length = args->length;
3221
1
  uint8_t *s = stream_pnt(peer->curr);
3222
1
  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
1
  if (peer->sort == BGP_PEER_EBGP &&
3234
1
      !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
3235
1
    zlog_warn(
3236
1
      "%pBP received AIGP attribute, but eBGP peer do not support it",
3237
1
      peer);
3238
1
    goto aigp_ignore;
3239
1
  }
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
1
aigp_ignore:
3252
1
  stream_forward_getp(peer->curr, length);
3253
3254
1
  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
455
{
3296
455
  bgp_size_t total = args->total;
3297
455
  struct transit *transit;
3298
455
  struct peer *const peer = args->peer;
3299
455
  struct attr *const attr = args->attr;
3300
455
  uint8_t *const startp = args->startp;
3301
455
  const uint8_t type = args->type;
3302
455
  const uint8_t flag = args->flags;
3303
455
  const bgp_size_t length = args->length;
3304
3305
455
  if (bgp_debug_update(peer, NULL, NULL, 1))
3306
0
    zlog_debug(
3307
455
      "%s Unknown attribute is received (type %d, length %d)",
3308
455
      peer->host, type, length);
3309
3310
  /* Forward read pointer of input stream. */
3311
455
  stream_forward_getp(peer->curr, length);
3312
3313
455
  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
455
  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
423
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3328
238
    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
185
  SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3335
3336
  /* Store transitive attribute to the end of attr->transit. */
3337
185
  transit = bgp_attr_get_transit(attr);
3338
185
  if (!transit)
3339
161
    transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
3340
3341
185
  transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3342
185
        transit->length + total);
3343
3344
185
  memcpy(transit->val + transit->length, startp, total);
3345
185
  transit->length += total;
3346
185
  bgp_attr_set_transit(attr, transit);
3347
3348
185
  return BGP_ATTR_PARSE_PROCEED;
3349
423
}
3350
3351
/* Well-known attribute check. */
3352
static int bgp_attr_check(struct peer *peer, struct attr *attr)
3353
314
{
3354
314
  uint8_t type = 0;
3355
3356
  /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3357
   * empty UPDATE.  */
3358
314
  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
314
  if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3367
29
       CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
3368
4
    return BGP_ATTR_PARSE_PROCEED;
3369
3370
310
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3371
39
    type = BGP_ATTR_ORIGIN;
3372
3373
310
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3374
38
    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
310
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3381
309
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3382
25
    type = BGP_ATTR_NEXT_HOP;
3383
3384
310
  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
310
  if (type) {
3392
40
    flog_warn(EC_BGP_MISSING_ATTRIBUTE,
3393
40
        "%s Missing well-known attribute %s.", peer->host,
3394
40
        lookup_msg(attr_str, type, NULL));
3395
40
    return BGP_ATTR_PARSE_WITHDRAW;
3396
40
  }
3397
270
  return BGP_ATTR_PARSE_PROCEED;
3398
310
}
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
616
{
3407
616
  enum bgp_attr_parse_ret ret;
3408
616
  uint8_t flag = 0;
3409
616
  uint8_t type = 0;
3410
616
  bgp_size_t length;
3411
616
  uint8_t *startp, *endp;
3412
616
  uint8_t *attr_endp;
3413
616
  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
616
  struct aspath *as4_path = NULL;
3418
616
  as_t as4_aggregator = 0;
3419
616
  struct in_addr as4_aggregator_addr = {.s_addr = 0};
3420
616
  struct transit *transit;
3421
3422
  /* Initialize bitmap. */
3423
616
  memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3424
3425
  /* End pointer of BGP attribute. */
3426
616
  endp = BGP_INPUT_PNT(peer) + size;
3427
3428
  /* Get attributes to the end of attribute length. */
3429
2.21k
  while (BGP_INPUT_PNT(peer) < endp) {
3430
    /* Check remaining length check.*/
3431
1.90k
    if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) {
3432
      /* XXX warning: long int format, int arg (arg 5) */
3433
3
      flog_warn(
3434
3
        EC_BGP_ATTRIBUTE_TOO_SMALL,
3435
3
        "%s: error BGP attribute length %lu is smaller than min len",
3436
3
        peer->host,
3437
3
        (unsigned long)(endp
3438
3
            - stream_pnt(BGP_INPUT(peer))));
3439
3440
3
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3441
3
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3442
3
      ret = BGP_ATTR_PARSE_ERROR;
3443
3
      goto done;
3444
3
    }
3445
3446
    /* Fetch attribute flag and type. */
3447
1.89k
    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.89k
    flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3452
1.89k
    type = stream_getc(BGP_INPUT(peer));
3453
3454
    /* Check whether Extended-Length applies and is in bounds */
3455
1.89k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3456
438
        && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
3457
0
      flog_warn(
3458
0
        EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
3459
0
        "%s: Extended length set, but just %lu bytes of attr header",
3460
0
        peer->host,
3461
0
        (unsigned long)(endp
3462
0
            - stream_pnt(BGP_INPUT(peer))));
3463
3464
0
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3465
0
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3466
0
      ret = BGP_ATTR_PARSE_ERROR;
3467
0
      goto done;
3468
0
    }
3469
3470
    /* Check extended attribue length bit. */
3471
1.89k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3472
438
      length = stream_getw(BGP_INPUT(peer));
3473
1.46k
    else
3474
1.46k
      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.89k
    if (CHECK_BITMAP(seen, type)) {
3481
7
      flog_warn(
3482
7
        EC_BGP_ATTRIBUTE_REPEATED,
3483
7
        "%s: error BGP attribute type %d appears twice in a message",
3484
7
        peer->host, type);
3485
3486
7
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3487
7
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3488
7
      ret = BGP_ATTR_PARSE_ERROR;
3489
7
      goto done;
3490
7
    }
3491
3492
    /* Set type to bitmap to check duplicate attribute.  `type' is
3493
       unsigned char so it never overflow bitmap range. */
3494
3495
1.89k
    SET_BITMAP(seen, type);
3496
3497
    /* Overflow check. */
3498
1.89k
    attr_endp = BGP_INPUT_PNT(peer) + length;
3499
3500
1.89k
    if (attr_endp > endp) {
3501
99
      flog_warn(
3502
99
        EC_BGP_ATTRIBUTE_TOO_LARGE,
3503
99
        "%s: BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p",
3504
99
        peer->host, type, length, size, attr_endp,
3505
99
        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
99
      unsigned char ndata[peer->max_packet_size];
3527
99
      memset(ndata, 0x00, sizeof(ndata));
3528
99
      size_t lfl =
3529
99
        CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3530
      /* Rewind to end of flag field */
3531
99
      stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
3532
      /* Type */
3533
99
      stream_get(&ndata[0], BGP_INPUT(peer), 1);
3534
      /* Length */
3535
99
      stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3536
      /* Value */
3537
99
      size_t atl = attr_endp - startp;
3538
99
      size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3539
99
      stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3540
3541
99
      bgp_notify_send_with_data(
3542
99
        peer, BGP_NOTIFY_UPDATE_ERR,
3543
99
        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3544
99
        ndl + lfl + 1);
3545
3546
99
      ret = BGP_ATTR_PARSE_ERROR;
3547
99
      goto done;
3548
99
    }
3549
3550
1.79k
    struct bgp_attr_parser_args attr_args = {
3551
1.79k
      .peer = peer,
3552
1.79k
      .length = length,
3553
1.79k
      .attr = attr,
3554
1.79k
      .type = type,
3555
1.79k
      .flags = flag,
3556
1.79k
      .startp = startp,
3557
1.79k
      .total = attr_endp - startp,
3558
1.79k
    };
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.79k
    if (bgp_attr_flag_invalid(&attr_args)) {
3567
46
      ret = bgp_attr_malformed(
3568
46
        &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3569
46
        attr_args.total);
3570
46
      if (ret == BGP_ATTR_PARSE_PROCEED)
3571
14
        continue;
3572
32
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3573
32
      goto done;
3574
46
    }
3575
3576
    /* OK check attribute and store it's value. */
3577
1.74k
    switch (type) {
3578
275
    case BGP_ATTR_ORIGIN:
3579
275
      ret = bgp_attr_origin(&attr_args);
3580
275
      break;
3581
293
    case BGP_ATTR_AS_PATH:
3582
293
      ret = bgp_attr_aspath(&attr_args);
3583
293
      break;
3584
33
    case BGP_ATTR_AS4_PATH:
3585
33
      ret = bgp_attr_as4_path(&attr_args, &as4_path);
3586
33
      break;
3587
61
    case BGP_ATTR_NEXT_HOP:
3588
61
      ret = bgp_attr_nexthop(&attr_args);
3589
61
      break;
3590
7
    case BGP_ATTR_MULTI_EXIT_DISC:
3591
7
      ret = bgp_attr_med(&attr_args);
3592
7
      break;
3593
5
    case BGP_ATTR_LOCAL_PREF:
3594
5
      ret = bgp_attr_local_pref(&attr_args);
3595
5
      break;
3596
6
    case BGP_ATTR_ATOMIC_AGGREGATE:
3597
6
      ret = bgp_attr_atomic(&attr_args);
3598
6
      break;
3599
2
    case BGP_ATTR_AGGREGATOR:
3600
2
      ret = bgp_attr_aggregator(&attr_args);
3601
2
      break;
3602
3
    case BGP_ATTR_AS4_AGGREGATOR:
3603
3
      ret = bgp_attr_as4_aggregator(&attr_args,
3604
3
                  &as4_aggregator,
3605
3
                  &as4_aggregator_addr);
3606
3
      break;
3607
27
    case BGP_ATTR_COMMUNITIES:
3608
27
      ret = bgp_attr_community(&attr_args);
3609
27
      break;
3610
14
    case BGP_ATTR_LARGE_COMMUNITIES:
3611
14
      ret = bgp_attr_large_community(&attr_args);
3612
14
      break;
3613
10
    case BGP_ATTR_ORIGINATOR_ID:
3614
10
      ret = bgp_attr_originator_id(&attr_args);
3615
10
      break;
3616
18
    case BGP_ATTR_CLUSTER_LIST:
3617
18
      ret = bgp_attr_cluster_list(&attr_args);
3618
18
      break;
3619
341
    case BGP_ATTR_MP_REACH_NLRI:
3620
341
      ret = bgp_mp_reach_parse(&attr_args, mp_update);
3621
341
      break;
3622
11
    case BGP_ATTR_MP_UNREACH_NLRI:
3623
11
      ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3624
11
      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
7
    case BGP_ATTR_ENCAP:
3632
7
      ret = bgp_attr_encap(&attr_args);
3633
7
      break;
3634
38
    case BGP_ATTR_PREFIX_SID:
3635
38
      ret = bgp_attr_prefix_sid(&attr_args);
3636
38
      break;
3637
1
    case BGP_ATTR_PMSI_TUNNEL:
3638
1
      ret = bgp_attr_pmsi_tunnel(&attr_args);
3639
1
      break;
3640
28
    case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3641
28
      ret = bgp_attr_ipv6_ext_communities(&attr_args);
3642
28
      break;
3643
0
    case BGP_ATTR_OTC:
3644
0
      ret = bgp_attr_otc(&attr_args);
3645
0
      break;
3646
1
    case BGP_ATTR_AIGP:
3647
1
      ret = bgp_attr_aigp(&attr_args);
3648
1
      break;
3649
455
    default:
3650
455
      ret = bgp_attr_unknown(&attr_args);
3651
455
      break;
3652
1.74k
    }
3653
3654
1.74k
    if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3655
55
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3656
55
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3657
55
      ret = BGP_ATTR_PARSE_ERROR;
3658
55
      goto done;
3659
55
    }
3660
3661
1.69k
    if (ret == BGP_ATTR_PARSE_EOR) {
3662
46
      goto done;
3663
46
    }
3664
3665
1.64k
    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.64k
    if (ret == BGP_ATTR_PARSE_WITHDRAW) {
3672
58
      flog_warn(
3673
58
        EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
3674
58
        "%s: Attribute %s, parse error - treating as withdrawal",
3675
58
        peer->host, lookup_msg(attr_str, type, NULL));
3676
58
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3677
58
      goto done;
3678
58
    }
3679
3680
    /* Check the fetched length. */
3681
1.58k
    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.58k
  }
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
314
  if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3701
314
    attr->label_index = BGP_INVALID_LABEL_INDEX;
3702
3703
  /* Check final read pointer is same as end pointer. */
3704
314
  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
314
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3729
1
      && !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
314
  ret = bgp_attr_check(peer, attr);
3738
314
  if (ret < 0)
3739
40
    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
274
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3758
270
      && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3759
270
          &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
274
  if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3771
270
    ret = bgp_attr_aspath_check(peer, attr);
3772
270
    if (ret != BGP_ATTR_PARSE_PROCEED)
3773
0
      goto done;
3774
270
  }
3775
3776
274
  ret = BGP_ATTR_PARSE_PROCEED;
3777
616
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
616
  aspath_unintern(&as4_path);
3791
3792
616
  transit = bgp_attr_get_transit(attr);
3793
616
  if (ret != BGP_ATTR_PARSE_ERROR) {
3794
    /* Finally intern unknown attribute. */
3795
450
    if (transit)
3796
147
      bgp_attr_set_transit(attr, transit_intern(transit));
3797
450
    if (attr->encap_subtlvs)
3798
6
      attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3799
6
                 ENCAP_SUBTLV_TYPE);
3800
450
#ifdef ENABLE_BGP_VNC
3801
450
    struct bgp_attr_encap_subtlv *vnc_subtlvs =
3802
450
      bgp_attr_get_vnc_subtlvs(attr);
3803
3804
450
    if (vnc_subtlvs)
3805
0
      bgp_attr_set_vnc_subtlvs(
3806
0
        attr,
3807
0
        encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
3808
450
#endif
3809
450
  } else {
3810
166
    if (transit) {
3811
14
      transit_free(transit);
3812
14
      bgp_attr_set_transit(attr, NULL);
3813
14
    }
3814
3815
166
    bgp_attr_flush_encap(attr);
3816
166
  };
3817
3818
  /* Sanity checks */
3819
616
  transit = bgp_attr_get_transit(attr);
3820
616
  if (transit)
3821
147
    assert(transit->refcnt > 0);
3822
616
  if (attr->encap_subtlvs)
3823
6
    assert(attr->encap_subtlvs->refcnt > 0);
3824
616
#ifdef ENABLE_BGP_VNC
3825
616
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
3826
616
    bgp_attr_get_vnc_subtlvs(attr);
3827
3828
616
  if (vnc_subtlvs)
3829
0
    assert(vnc_subtlvs->refcnt > 0);
3830
616
#endif
3831
3832
616
  return ret;
3833
616
}
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.4k
  for (i = 0; i < ecom->size; i++) {
3852
10.3k
    uint8_t *pnt;
3853
10.3k
    uint8_t type, sub_type;
3854
3855
10.3k
    pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3856
10.3k
    type = pnt[0];
3857
10.3k
    sub_type = pnt[1];
3858
10.3k
    if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3859
182
          sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3860
10.3k
      continue;
3861
1
    *tunnel_type = ((pnt[6] << 8) | pnt[7]);
3862
1
    return;
3863
10.3k
  }
3864
3865
108
  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
1
{
5182
1
  bool discard = peer->discard_attrs[type];
5183
1
  bool withdraw = peer->withdraw_attrs[type];
5184
5185
1
  if (bgp_debug_update(peer, NULL, NULL, 1) && (discard || withdraw))
5186
0
    zlog_debug("%pBP: Ignoring attribute %s (%s)", peer,
5187
1
         lookup_msg(attr_str, type, NULL),
5188
1
         withdraw ? "treat-as-withdraw" : "discard");
5189
5190
1
  return withdraw ? BGP_ATTR_PARSE_WITHDRAW : BGP_ATTR_PARSE_PROCEED;
5191
1
}