Coverage Report

Created: 2025-08-26 06:20

/src/frr/bgpd/bgp_attr.c
Line
Count
Source (jump to first uncovered line)
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
23
{
87
23
  const struct cluster_list *val = (const struct cluster_list *)p;
88
23
  struct cluster_list *cluster;
89
90
23
  cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list));
91
23
  cluster->length = val->length;
92
93
23
  if (cluster->length) {
94
23
    cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length);
95
23
    memcpy(cluster->list, val->list, val->length);
96
23
  } else
97
0
    cluster->list = NULL;
98
99
23
  cluster->refcnt = 0;
100
101
23
  return cluster;
102
23
}
103
104
/* Cluster list related functions. */
105
static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
106
23
{
107
23
  struct cluster_list tmp = {};
108
23
  struct cluster_list *cluster;
109
110
23
  tmp.length = length;
111
23
  tmp.list = length == 0 ? NULL : pnt;
112
113
23
  cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc);
114
23
  cluster->refcnt++;
115
23
  return cluster;
116
23
}
117
118
bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
119
13
{
120
13
  int i;
121
122
88
  for (i = 0; i < cluster->length / 4; i++)
123
86
    if (cluster->list[i].s_addr == originator.s_addr)
124
11
      return true;
125
2
  return false;
126
13
}
127
128
static unsigned int cluster_hash_key_make(const void *p)
129
46
{
130
46
  const struct cluster_list *cluster = p;
131
132
46
  return jhash(cluster->list, cluster->length, 0);
133
46
}
134
135
static bool cluster_hash_cmp(const void *p1, const void *p2)
136
23
{
137
23
  const struct cluster_list *cluster1 = p1;
138
23
  const struct cluster_list *cluster2 = p2;
139
140
23
  if (cluster1->list == cluster2->list)
141
23
    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
23
{
154
23
  XFREE(MTYPE_CLUSTER_VAL, cluster->list);
155
23
  XFREE(MTYPE_CLUSTER, cluster);
156
23
}
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
23
{
170
23
  if ((*cluster)->refcnt)
171
23
    (*cluster)->refcnt--;
172
173
23
  if ((*cluster)->refcnt == 0) {
174
23
    void *p = hash_release(cluster_hash, *cluster);
175
23
    assert(p == *cluster);
176
23
    cluster_free(*cluster);
177
23
    *cluster = NULL;
178
23
  }
179
23
}
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
751
  while (p) {
225
744
    next = p->next;
226
744
    p->next = NULL;
227
744
    XFREE(MTYPE_ENCAP_TLV, p);
228
744
    p = next;
229
744
  }
230
7
}
231
232
void bgp_attr_flush_encap(struct attr *attr)
233
196
{
234
196
  if (!attr)
235
0
    return;
236
237
196
  if (attr->encap_subtlvs) {
238
2
    encap_free(attr->encap_subtlvs);
239
2
    attr->encap_subtlvs = NULL;
240
2
  }
241
196
#ifdef ENABLE_BGP_VNC
242
196
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
243
196
    bgp_attr_get_vnc_subtlvs(attr);
244
245
196
  if (vnc_subtlvs) {
246
0
    encap_free(vnc_subtlvs);
247
0
    bgp_attr_set_vnc_subtlvs(attr, NULL);
248
0
  }
249
196
#endif
250
196
}
251
252
/*
253
 * Compare encap sub-tlv chains
254
 *
255
 *  1 = equivalent
256
 *  0 = not equivalent
257
 *
258
 * This algorithm could be made faster if needed
259
 */
260
static bool encap_same(const struct bgp_attr_encap_subtlv *h1,
261
           const struct bgp_attr_encap_subtlv *h2)
262
5
{
263
5
  const struct bgp_attr_encap_subtlv *p;
264
5
  const struct bgp_attr_encap_subtlv *q;
265
266
5
  if (h1 == h2)
267
5
    return true;
268
0
  if (h1 == NULL || h2 == NULL)
269
0
    return false;
270
271
0
  for (p = h1; p; p = p->next) {
272
0
    for (q = h2; q; q = q->next) {
273
0
      if ((p->type == q->type) && (p->length == q->length)
274
0
          && !memcmp(p->value, q->value, p->length)) {
275
276
0
        break;
277
0
      }
278
0
    }
279
0
    if (!q)
280
0
      return false;
281
0
  }
282
283
0
  for (p = h2; p; p = p->next) {
284
0
    for (q = h1; q; q = q->next) {
285
0
      if ((p->type == q->type) && (p->length == q->length)
286
0
          && !memcmp(p->value, q->value, p->length)) {
287
288
0
        break;
289
0
      }
290
0
    }
291
0
    if (!q)
292
0
      return false;
293
0
  }
294
295
0
  return true;
296
0
}
297
298
static void *encap_hash_alloc(void *p)
299
5
{
300
  /* Encap structure is already allocated.  */
301
5
  return p;
302
5
}
303
304
typedef enum {
305
  ENCAP_SUBTLV_TYPE,
306
#ifdef ENABLE_BGP_VNC
307
  VNC_SUBTLV_TYPE
308
#endif
309
} encap_subtlv_type;
310
311
static struct bgp_attr_encap_subtlv *
312
encap_intern(struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type)
313
5
{
314
5
  struct bgp_attr_encap_subtlv *find;
315
5
  struct hash *hash = encap_hash;
316
5
#ifdef ENABLE_BGP_VNC
317
5
  if (type == VNC_SUBTLV_TYPE)
318
0
    hash = vnc_hash;
319
5
#endif
320
321
5
  find = hash_get(hash, encap, encap_hash_alloc);
322
5
  if (find != encap)
323
0
    encap_free(encap);
324
5
  find->refcnt++;
325
326
5
  return find;
327
5
}
328
329
static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
330
         encap_subtlv_type type)
331
5
{
332
5
  struct bgp_attr_encap_subtlv *encap = *encapp;
333
5
  if (encap->refcnt)
334
5
    encap->refcnt--;
335
336
5
  if (encap->refcnt == 0) {
337
5
    struct hash *hash = encap_hash;
338
5
#ifdef ENABLE_BGP_VNC
339
5
    if (type == VNC_SUBTLV_TYPE)
340
0
      hash = vnc_hash;
341
5
#endif
342
5
    hash_release(hash, encap);
343
5
    encap_free(encap);
344
5
    *encapp = NULL;
345
5
  }
346
5
}
347
348
static unsigned int encap_hash_key_make(const void *p)
349
10
{
350
10
  const struct bgp_attr_encap_subtlv *encap = p;
351
352
10
  return jhash(encap->value, encap->length, 0);
353
10
}
354
355
static bool encap_hash_cmp(const void *p1, const void *p2)
356
5
{
357
5
  return encap_same((const struct bgp_attr_encap_subtlv *)p1,
358
5
        (const struct bgp_attr_encap_subtlv *)p2);
359
5
}
360
361
static void encap_init(void)
362
1
{
363
1
  encap_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
364
1
         "BGP Encap Hash");
365
1
#ifdef ENABLE_BGP_VNC
366
1
  vnc_hash = hash_create(encap_hash_key_make, encap_hash_cmp,
367
1
             "BGP VNC Hash");
368
1
#endif
369
1
}
370
371
static void encap_finish(void)
372
0
{
373
0
  hash_clean_and_free(&encap_hash, (void (*)(void *))encap_free);
374
0
#ifdef ENABLE_BGP_VNC
375
0
  hash_clean_and_free(&vnc_hash, (void (*)(void *))encap_free);
376
0
#endif
377
0
}
378
379
static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
380
0
{
381
0
  if (!a1 && a2)
382
0
    return false;
383
0
  if (!a2 && a1)
384
0
    return false;
385
0
  if (!a1 && !a2)
386
0
    return true;
387
388
0
  return bgp_route_evpn_same(bgp_attr_get_evpn_overlay(a1),
389
0
           bgp_attr_get_evpn_overlay(a2));
390
0
}
391
392
/* Unknown transit attribute. */
393
static struct hash *transit_hash;
394
395
static void transit_free(struct transit *transit)
396
90
{
397
90
  XFREE(MTYPE_TRANSIT_VAL, transit->val);
398
90
  XFREE(MTYPE_TRANSIT, transit);
399
90
}
400
401
static void *transit_hash_alloc(void *p)
402
73
{
403
  /* Transit structure is already allocated.  */
404
73
  return p;
405
73
}
406
407
static struct transit *transit_intern(struct transit *transit)
408
73
{
409
73
  struct transit *find;
410
411
73
  find = hash_get(transit_hash, transit, transit_hash_alloc);
412
73
  if (find != transit)
413
0
    transit_free(transit);
414
73
  find->refcnt++;
415
416
73
  return find;
417
73
}
418
419
static void transit_unintern(struct transit **transit)
420
73
{
421
73
  if ((*transit)->refcnt)
422
73
    (*transit)->refcnt--;
423
424
73
  if ((*transit)->refcnt == 0) {
425
73
    hash_release(transit_hash, *transit);
426
73
    transit_free(*transit);
427
73
    *transit = NULL;
428
73
  }
429
73
}
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
9
{
544
9
  return p;
545
9
}
546
547
static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn *l3vpn)
548
13
{
549
13
  XFREE(MTYPE_BGP_SRV6_L3VPN, l3vpn);
550
13
}
551
552
static struct bgp_attr_srv6_l3vpn *
553
srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn *l3vpn)
554
9
{
555
9
  struct bgp_attr_srv6_l3vpn *find;
556
557
9
  find = hash_get(srv6_l3vpn_hash, l3vpn, srv6_l3vpn_hash_alloc);
558
9
  if (find != l3vpn)
559
0
    srv6_l3vpn_free(l3vpn);
560
9
  find->refcnt++;
561
9
  return find;
562
9
}
563
564
static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn **l3vpnp)
565
13
{
566
13
  struct bgp_attr_srv6_l3vpn *l3vpn = *l3vpnp;
567
568
13
  if (l3vpn->refcnt)
569
9
    l3vpn->refcnt--;
570
571
13
  if (l3vpn->refcnt == 0) {
572
13
    hash_release(srv6_l3vpn_hash, l3vpn);
573
13
    srv6_l3vpn_free(l3vpn);
574
13
    *l3vpnp = NULL;
575
13
  }
576
13
}
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
22
{
615
22
  const struct bgp_attr_srv6_l3vpn *l3vpn = p;
616
22
  uint32_t key = 0;
617
618
22
  key = jhash(&l3vpn->sid, 16, key);
619
22
  key = jhash_1word(l3vpn->sid_flags, key);
620
22
  key = jhash_1word(l3vpn->endpoint_behavior, key);
621
22
  key = jhash_1word(l3vpn->loc_block_len, key);
622
22
  key = jhash_1word(l3vpn->loc_node_len, key);
623
22
  key = jhash_1word(l3vpn->func_len, key);
624
22
  key = jhash_1word(l3vpn->arg_len, key);
625
22
  key = jhash_1word(l3vpn->transposition_len, key);
626
22
  key = jhash_1word(l3vpn->transposition_offset, key);
627
22
  return key;
628
22
}
629
630
static bool srv6_l3vpn_hash_cmp(const void *p1, const void *p2)
631
9
{
632
9
  const struct bgp_attr_srv6_l3vpn *l3vpn1 = p1;
633
9
  const struct bgp_attr_srv6_l3vpn *l3vpn2 = p2;
634
635
9
  return sid_same(&l3vpn1->sid, &l3vpn2->sid)
636
9
         && l3vpn1->sid_flags == l3vpn2->sid_flags
637
9
         && l3vpn1->endpoint_behavior == l3vpn2->endpoint_behavior
638
9
         && l3vpn1->loc_block_len == l3vpn2->loc_block_len
639
9
         && l3vpn1->loc_node_len == l3vpn2->loc_node_len
640
9
         && l3vpn1->func_len == l3vpn2->func_len
641
9
         && l3vpn1->arg_len == l3vpn2->arg_len
642
9
         && l3vpn1->transposition_len == l3vpn2->transposition_len
643
9
         && l3vpn1->transposition_offset == l3vpn2->transposition_offset;
644
9
}
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
146
{
705
146
  const struct transit *transit = p;
706
707
146
  return jhash(transit->val, transit->length, 0);
708
146
}
709
710
static bool transit_hash_cmp(const void *p1, const void *p2)
711
73
{
712
73
  const struct transit *transit1 = p1;
713
73
  const struct transit *transit2 = p2;
714
715
73
  return (transit1->length == transit2->length
716
73
    && memcmp(transit1->val, transit2->val, transit1->length) == 0);
717
73
}
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
473
{
1188
473
  struct ecommunity *ecomm = NULL;
1189
473
  struct ecommunity *ipv6_ecomm = NULL;
1190
473
  struct cluster_list *cluster;
1191
473
  struct lcommunity *lcomm = NULL;
1192
473
  struct community *comm = NULL;
1193
1194
  /* aspath refcount shoud be decrement. */
1195
473
  aspath_unintern(&attr->aspath);
1196
473
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
1197
1198
473
  comm = bgp_attr_get_community(attr);
1199
473
  community_unintern(&comm);
1200
473
  bgp_attr_set_community(attr, NULL);
1201
1202
473
  ecomm = bgp_attr_get_ecommunity(attr);
1203
473
  ecommunity_unintern(&ecomm);
1204
473
  bgp_attr_set_ecommunity(attr, NULL);
1205
1206
473
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1207
473
  ecommunity_unintern(&ipv6_ecomm);
1208
473
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1209
1210
473
  lcomm = bgp_attr_get_lcommunity(attr);
1211
473
  lcommunity_unintern(&lcomm);
1212
473
  bgp_attr_set_lcommunity(attr, NULL);
1213
1214
473
  cluster = bgp_attr_get_cluster(attr);
1215
473
  if (cluster) {
1216
23
    cluster_unintern(&cluster);
1217
23
    bgp_attr_set_cluster(attr, cluster);
1218
23
  }
1219
473
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
1220
1221
473
  struct transit *transit = bgp_attr_get_transit(attr);
1222
1223
473
  if (transit) {
1224
73
    transit_unintern(&transit);
1225
73
    bgp_attr_set_transit(attr, transit);
1226
73
  }
1227
1228
473
  if (attr->encap_subtlvs)
1229
5
    encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
1230
1231
473
#ifdef ENABLE_BGP_VNC
1232
473
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1233
473
    bgp_attr_get_vnc_subtlvs(attr);
1234
1235
473
  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
473
#endif
1240
1241
473
  if (attr->srv6_l3vpn)
1242
13
    srv6_l3vpn_unintern(&attr->srv6_l3vpn);
1243
1244
473
  if (attr->srv6_vpn)
1245
0
    srv6_vpn_unintern(&attr->srv6_vpn);
1246
473
}
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.04k
{
1273
2.04k
  struct ecommunity *ecomm;
1274
2.04k
  struct ecommunity *ipv6_ecomm;
1275
2.04k
  struct cluster_list *cluster;
1276
2.04k
  struct lcommunity *lcomm;
1277
2.04k
  struct community *comm;
1278
1279
2.04k
  if (attr->aspath && !attr->aspath->refcnt) {
1280
0
    aspath_free(attr->aspath);
1281
0
    attr->aspath = NULL;
1282
0
  }
1283
2.04k
  comm = bgp_attr_get_community(attr);
1284
2.04k
  if (comm && !comm->refcnt)
1285
373
    community_free(&comm);
1286
2.04k
  bgp_attr_set_community(attr, NULL);
1287
1288
2.04k
  ecomm = bgp_attr_get_ecommunity(attr);
1289
2.04k
  if (ecomm && !ecomm->refcnt)
1290
0
    ecommunity_free(&ecomm);
1291
2.04k
  bgp_attr_set_ecommunity(attr, NULL);
1292
1293
2.04k
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1294
2.04k
  if (ipv6_ecomm && !ipv6_ecomm->refcnt)
1295
0
    ecommunity_free(&ipv6_ecomm);
1296
2.04k
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1297
1298
2.04k
  lcomm = bgp_attr_get_lcommunity(attr);
1299
2.04k
  if (lcomm && !lcomm->refcnt)
1300
0
    lcommunity_free(&lcomm);
1301
2.04k
  bgp_attr_set_lcommunity(attr, NULL);
1302
1303
2.04k
  cluster = bgp_attr_get_cluster(attr);
1304
2.04k
  if (cluster && !cluster->refcnt) {
1305
0
    cluster_free(cluster);
1306
0
    bgp_attr_set_cluster(attr, NULL);
1307
0
  }
1308
1309
2.04k
  struct transit *transit = bgp_attr_get_transit(attr);
1310
1311
2.04k
  if (transit && !transit->refcnt) {
1312
0
    transit_free(transit);
1313
0
    bgp_attr_set_transit(attr, NULL);
1314
0
  }
1315
2.04k
  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.04k
  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.04k
  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.04k
#ifdef ENABLE_BGP_VNC
1328
2.04k
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1329
2.04k
    bgp_attr_get_vnc_subtlvs(attr);
1330
1331
2.04k
  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.04k
#endif
1336
2.04k
}
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
160
{
1347
160
  struct peer *const peer = args->peer;
1348
160
  struct attr *const attr = args->attr;
1349
160
  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
160
  uint8_t *notify_datap = (length > 0 ? args->startp : NULL);
1355
1356
160
  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
160
  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
160
  stream_set_getp(BGP_INPUT(peer),
1375
160
      (args->startp - STREAM_DATA(BGP_INPUT(peer)))
1376
160
        + args->total);
1377
1378
160
  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
1
  case BGP_ATTR_AS4_AGGREGATOR:
1385
1
  case BGP_ATTR_AGGREGATOR:
1386
4
  case BGP_ATTR_ATOMIC_AGGREGATE:
1387
4
    return BGP_ATTR_PARSE_PROCEED;
1388
1389
  /* Core attributes, particularly ones which may influence route
1390
   * selection, should be treat-as-withdraw.
1391
   */
1392
13
  case BGP_ATTR_ORIGIN:
1393
30
  case BGP_ATTR_AS_PATH:
1394
46
  case BGP_ATTR_AS4_PATH:
1395
50
  case BGP_ATTR_NEXT_HOP:
1396
56
  case BGP_ATTR_MULTI_EXIT_DISC:
1397
56
  case BGP_ATTR_LOCAL_PREF:
1398
59
  case BGP_ATTR_COMMUNITIES:
1399
63
  case BGP_ATTR_EXT_COMMUNITIES:
1400
64
  case BGP_ATTR_IPV6_EXT_COMMUNITIES:
1401
68
  case BGP_ATTR_LARGE_COMMUNITIES:
1402
68
  case BGP_ATTR_ORIGINATOR_ID:
1403
69
  case BGP_ATTR_CLUSTER_LIST:
1404
69
  case BGP_ATTR_PMSI_TUNNEL:
1405
75
  case BGP_ATTR_ENCAP:
1406
76
  case BGP_ATTR_OTC:
1407
76
    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
160
  }
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
80
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
1420
80
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1421
80
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
1422
14
    return BGP_ATTR_PARSE_WITHDRAW;
1423
1424
  /* default to reset */
1425
66
  return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1426
80
}
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
10
{
1438
10
  uint8_t seen = 0, i;
1439
10
  uint8_t real_flags = args->flags;
1440
10
  const uint8_t attr_code = args->type;
1441
1442
10
  desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1443
10
  real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1444
40
  for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1445
30
    if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1446
30
        != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
1447
14
      flog_err(EC_BGP_ATTR_FLAG,
1448
14
         "%s attribute must%s be flagged as \"%s\"",
1449
14
         lookup_msg(attr_str, attr_code, NULL),
1450
14
         CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1451
14
           ? ""
1452
14
           : " not",
1453
14
         attr_flag_str[i].str);
1454
14
      seen = 1;
1455
14
    }
1456
10
  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
10
}
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.08k
{
1498
1.08k
  uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
1499
1.08k
  const uint8_t flags = args->flags;
1500
1.08k
  const uint8_t attr_code = args->type;
1501
1502
  /* there may be attributes we don't know about */
1503
1.08k
  if (attr_code > attr_flags_values_max)
1504
237
    return false;
1505
851
  if (attr_flags_values[attr_code] == 0)
1506
76
    return false;
1507
1508
  /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1509
   * to
1510
   * 1."
1511
   */
1512
775
  if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
1513
775
      && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
1514
30
    flog_err(
1515
30
      EC_BGP_ATTR_FLAG,
1516
30
      "%s well-known attributes must have transitive flag set (%x)",
1517
30
      lookup_msg(attr_str, attr_code, NULL), flags);
1518
30
    return true;
1519
30
  }
1520
1521
  /* "For well-known attributes and for optional non-transitive
1522
   * attributes,
1523
   *  the Partial bit MUST be set to 0."
1524
   */
1525
745
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
1526
203
    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
203
    if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1533
203
        && !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
203
  }
1540
1541
  /* Optional transitive attributes may go through speakers that don't
1542
   * reocgnise them and set the Partial bit.
1543
   */
1544
743
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1545
743
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
1546
268
    SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
1547
1548
743
  if ((flags & ~mask) == attr_flags_values[attr_code])
1549
733
    return false;
1550
1551
10
  bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
1552
10
  return true;
1553
743
}
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
90
{
1559
90
  struct peer *const peer = args->peer;
1560
90
  struct attr *const attr = args->attr;
1561
90
  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
90
  if (length != 1) {
1569
0
    flog_err(EC_BGP_ATTR_LEN,
1570
0
       "Origin attribute length is not one %d", length);
1571
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1572
0
            args->total);
1573
0
  }
1574
1575
  /* Fetch origin attribute. */
1576
90
  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
90
  if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
1582
90
      && (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
89
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1591
1592
89
  return 0;
1593
90
}
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
112
{
1599
112
  struct attr *const attr = args->attr;
1600
112
  struct peer *const peer = args->peer;
1601
112
  const bgp_size_t length = args->length;
1602
112
  enum asnotation_mode asnotation;
1603
1604
112
  asnotation = bgp_get_asnotation(
1605
112
    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
112
  attr->aspath =
1611
112
    aspath_parse(peer->curr, length,
1612
112
           CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
1613
112
             CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
1614
112
           asnotation);
1615
1616
  /* In case of IBGP, length will be zero. */
1617
112
  if (!attr->aspath) {
1618
9
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1619
9
       "Malformed AS path from %s, length is %d", peer->host,
1620
9
       length);
1621
9
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1622
9
            0);
1623
9
  }
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
103
  if (peer->bgp && peer->bgp->reject_as_sets &&
1631
103
      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
103
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1641
1642
103
  return BGP_ATTR_PARSE_PROCEED;
1643
103
}
1644
1645
static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
1646
                 struct attr *const attr)
1647
89
{
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
89
  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
89
  (void)peer_sort(peer);
1664
1665
  /* Confederation sanity check. */
1666
89
  if ((peer->sort == BGP_PEER_CONFED
1667
89
       && !aspath_left_confed_check(attr->aspath))
1668
89
      || (peer->sort == BGP_PEER_EBGP
1669
89
    && 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
89
  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
89
  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
89
  if (peer->change_local_as
1697
89
      && !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
89
  return BGP_ATTR_PARSE_PROCEED;
1705
89
}
1706
1707
/* Parse AS4 path information.  This function is another wrapper of
1708
   aspath_parse. */
1709
static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
1710
           struct aspath **as4_path)
1711
41
{
1712
41
  struct peer *const peer = args->peer;
1713
41
  struct attr *const attr = args->attr;
1714
41
  const bgp_size_t length = args->length;
1715
41
  enum asnotation_mode asnotation;
1716
1717
41
  asnotation = bgp_get_asnotation(peer->bgp);
1718
1719
41
  *as4_path = aspath_parse(peer->curr, length, 1, asnotation);
1720
1721
  /* In case of IBGP, length will be zero. */
1722
41
  if (!*as4_path) {
1723
16
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1724
16
       "Malformed AS4 path from %s, length is %d", peer->host,
1725
16
       length);
1726
16
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1727
16
            0);
1728
16
  }
1729
1730
  /* Conformant BGP speakers SHOULD NOT send BGP
1731
   * UPDATE messages containing AS_SET or AS_CONFED_SET.  Upon receipt of
1732
   * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1733
   * withdraw" error handling behavior as per [RFC7606].
1734
   */
1735
25
  if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
1736
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1737
0
       "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1738
0
       peer);
1739
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1740
0
            0);
1741
0
  }
1742
1743
  /* Set aspath attribute flag. */
1744
25
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1745
1746
25
  return BGP_ATTR_PARSE_PROCEED;
1747
25
}
1748
1749
/*
1750
 * Check that the nexthop attribute is valid.
1751
 */
1752
enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
1753
                 struct attr *attr)
1754
2
{
1755
2
  struct bgp *bgp = peer->bgp;
1756
1757
2
  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
1
  return BGP_ATTR_PARSE_PROCEED;
1773
2
}
1774
1775
/* Nexthop attribute. */
1776
static enum bgp_attr_parse_ret
1777
bgp_attr_nexthop(struct bgp_attr_parser_args *args)
1778
52
{
1779
52
  struct peer *const peer = args->peer;
1780
52
  struct attr *const attr = args->attr;
1781
52
  const bgp_size_t length = args->length;
1782
1783
  /* Check nexthop attribute length. */
1784
52
  if (length != 4) {
1785
0
    flog_err(EC_BGP_ATTR_LEN,
1786
0
       "Nexthop attribute length isn't four [%d]", length);
1787
1788
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1789
0
            args->total);
1790
0
  }
1791
1792
52
  attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
1793
52
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1794
1795
52
  return BGP_ATTR_PARSE_PROCEED;
1796
52
}
1797
1798
/* MED atrribute. */
1799
static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
1800
4
{
1801
4
  struct peer *const peer = args->peer;
1802
4
  struct attr *const attr = args->attr;
1803
4
  const bgp_size_t length = args->length;
1804
1805
  /* Length check. */
1806
4
  if (length != 4) {
1807
0
    flog_err(EC_BGP_ATTR_LEN,
1808
0
       "MED attribute length isn't four [%d]", length);
1809
1810
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1811
0
            args->total);
1812
0
  }
1813
1814
4
  attr->med = stream_getl(peer->curr);
1815
1816
4
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1817
1818
4
  return BGP_ATTR_PARSE_PROCEED;
1819
4
}
1820
1821
/* Local preference attribute. */
1822
static enum bgp_attr_parse_ret
1823
bgp_attr_local_pref(struct bgp_attr_parser_args *args)
1824
4
{
1825
4
  struct peer *const peer = args->peer;
1826
4
  struct attr *const attr = args->attr;
1827
4
  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
4
  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
4
  if (peer->sort == BGP_PEER_EBGP) {
1845
4
    STREAM_FORWARD_GETP(peer->curr, length);
1846
4
    return BGP_ATTR_PARSE_PROCEED;
1847
4
  }
1848
1849
0
  STREAM_GETL(peer->curr, attr->local_pref);
1850
1851
  /* Set the local-pref flag. */
1852
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1853
1854
0
  return BGP_ATTR_PARSE_PROCEED;
1855
1856
0
stream_failure:
1857
0
  return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1858
0
          args->total);
1859
0
}
1860
1861
/* Atomic aggregate. */
1862
static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
1863
7
{
1864
7
  struct peer *const peer = args->peer;
1865
7
  struct attr *const attr = args->attr;
1866
7
  const bgp_size_t length = args->length;
1867
1868
  /* Length check. */
1869
7
  if (length != 0) {
1870
0
    flog_err(EC_BGP_ATTR_LEN,
1871
0
       "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1872
0
       length);
1873
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1874
0
            args->total);
1875
0
  }
1876
1877
7
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1878
0
    goto atomic_ignore;
1879
1880
  /* Set atomic aggregate flag. */
1881
7
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1882
1883
7
  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
7
}
1890
1891
/* Aggregator attribute */
1892
static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
1893
0
{
1894
0
  struct peer *const peer = args->peer;
1895
0
  struct attr *const attr = args->attr;
1896
0
  const bgp_size_t length = args->length;
1897
0
  as_t aggregator_as;
1898
1899
0
  int wantedlen = 6;
1900
1901
  /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */
1902
0
  if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
1903
0
      && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV))
1904
0
    wantedlen = 8;
1905
1906
0
  if (length != wantedlen) {
1907
0
    flog_err(EC_BGP_ATTR_LEN,
1908
0
       "AGGREGATOR attribute length isn't %u [%u]", wantedlen,
1909
0
       length);
1910
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1911
0
            args->total);
1912
0
  }
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
0
{
1956
0
  struct peer *const peer = args->peer;
1957
0
  struct attr *const attr = args->attr;
1958
0
  const bgp_size_t length = args->length;
1959
0
  as_t aggregator_as;
1960
1961
0
  if (length != 8) {
1962
0
    flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1963
0
       length);
1964
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1965
0
            0);
1966
0
  }
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
89
{
2008
89
  int ignore_as4_path = 0;
2009
89
  struct aspath *newpath;
2010
2011
89
  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
89
  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
89
    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
89
    return BGP_ATTR_PARSE_PROCEED;
2041
89
  }
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
34
{
2108
34
  struct peer *const peer = args->peer;
2109
34
  struct attr *const attr = args->attr;
2110
34
  const bgp_size_t length = args->length;
2111
2112
34
  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
34
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2119
0
    goto community_ignore;
2120
2121
34
  bgp_attr_set_community(
2122
34
    attr,
2123
34
    community_parse((uint32_t *)stream_pnt(peer->curr), length));
2124
2125
  /* XXX: fix community_parse to use stream API and remove this */
2126
34
  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
34
  if (!bgp_attr_get_community(attr))
2132
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2133
3
            args->total);
2134
2135
31
  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
34
}
2142
2143
/* Originator ID attribute. */
2144
static enum bgp_attr_parse_ret
2145
bgp_attr_originator_id(struct bgp_attr_parser_args *args)
2146
2
{
2147
2
  struct peer *const peer = args->peer;
2148
2
  struct attr *const attr = args->attr;
2149
2
  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
2
  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
2
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2165
0
    goto originator_id_ignore;
2166
2167
2
  attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
2168
2169
2
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2170
2171
2
  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
2
}
2178
2179
/* Cluster list attribute. */
2180
static enum bgp_attr_parse_ret
2181
bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
2182
24
{
2183
24
  struct peer *const peer = args->peer;
2184
24
  struct attr *const attr = args->attr;
2185
24
  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
24
  if (length == 0 || length % 4) {
2193
1
    flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
2194
2195
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2196
1
            args->total);
2197
1
  }
2198
2199
23
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2200
0
    goto cluster_list_ignore;
2201
2202
23
  bgp_attr_set_cluster(
2203
23
    attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2204
23
            length));
2205
2206
  /* XXX: Fix cluster_parse to use stream API and then remove this */
2207
23
  stream_forward_getp(peer->curr, length);
2208
2209
23
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
2210
2211
23
  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
23
}
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
163
{
2223
163
  iana_afi_t pkt_afi;
2224
163
  afi_t afi;
2225
163
  iana_safi_t pkt_safi;
2226
163
  safi_t safi;
2227
163
  bgp_size_t nlri_len;
2228
163
  size_t start;
2229
163
  struct stream *s;
2230
163
  struct peer *const peer = args->peer;
2231
163
  struct attr *const attr = args->attr;
2232
163
  const bgp_size_t length = args->length;
2233
2234
  /* Set end of packet. */
2235
163
  s = BGP_INPUT(peer);
2236
163
  start = stream_get_getp(s);
2237
2238
/* safe to read statically sized header? */
2239
163
#define BGP_MP_REACH_MIN_SIZE 5
2240
475
#define LEN_LEFT  (length - (stream_get_getp(s) - start))
2241
163
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
2242
1
    zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2243
1
        __func__, peer->host, (unsigned long)length);
2244
1
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2245
1
  }
2246
2247
  /* Load AFI, SAFI. */
2248
162
  pkt_afi = stream_getw(s);
2249
162
  pkt_safi = stream_getc(s);
2250
2251
  /* Convert AFI, SAFI to internal values, check. */
2252
162
  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
1
    if (bgp_debug_update(peer, NULL, NULL, 0))
2258
0
      zlog_debug(
2259
1
        "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2260
1
        peer->host, iana_afi2str(pkt_afi),
2261
1
        iana_safi2str(pkt_safi));
2262
1
    return BGP_ATTR_PARSE_ERROR;
2263
1
  }
2264
2265
  /* Get nexthop length. */
2266
161
  attr->mp_nexthop_len = stream_getc(s);
2267
2268
161
  if (LEN_LEFT < attr->mp_nexthop_len) {
2269
1
    zlog_info(
2270
1
      "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2271
1
      __func__, peer->host, attr->mp_nexthop_len);
2272
1
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2273
1
  }
2274
2275
  /* Nexthop length check. */
2276
160
  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
17
  case BGP_ATTR_NHLEN_VPNV4:
2285
17
    stream_getl(s); /* RD high */
2286
17
    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
60
  case BGP_ATTR_NHLEN_IPV4:
2296
60
    stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2297
    /* Probably needed for RFC 2283 */
2298
60
    if (attr->nexthop.s_addr == INADDR_ANY)
2299
56
      memcpy(&attr->nexthop.s_addr,
2300
56
             &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2301
60
    break;
2302
97
  case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2303
97
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2304
97
    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
97
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2309
97
    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
97
    break;
2318
97
  case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2319
2
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
2320
2
    if (attr->mp_nexthop_len
2321
2
        == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2322
2
      stream_getl(s); /* RD high */
2323
2
      stream_getl(s); /* RD low */
2324
2
    }
2325
2
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2326
2
    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
2
    if (attr->mp_nexthop_len
2335
2
        == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2336
2
      stream_getl(s); /* RD high */
2337
2
      stream_getl(s); /* RD low */
2338
2
    }
2339
2
    stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
2340
2
    if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
2341
2
      if (bgp_debug_update(peer, NULL, NULL, 1))
2342
0
        zlog_debug(
2343
2
          "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2344
2
          peer->host, &attr->mp_nexthop_global,
2345
2
          &attr->mp_nexthop_local);
2346
2347
2
      attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
2348
2
    }
2349
2
    if (!peer->nexthop.ifp) {
2350
2
      zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2351
2
          peer->host);
2352
2
      return BGP_ATTR_PARSE_WITHDRAW;
2353
2
    }
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
160
  }
2361
2362
157
  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
157
  {
2369
157
    uint8_t val;
2370
157
    if ((val = stream_getc(s)))
2371
92
      flog_warn(
2372
157
        EC_BGP_DEFUNCT_SNPA_LEN,
2373
157
        "%s sent non-zero value, %u, for defunct SNPA-length field",
2374
157
        peer->host, val);
2375
157
  }
2376
2377
  /* must have nrli_len, what is left of the attribute */
2378
157
  nlri_len = LEN_LEFT;
2379
157
  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
157
  if (!nlri_len) {
2386
42
    zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2387
42
        __func__, peer->host);
2388
2389
42
    mp_update->afi = afi;
2390
42
    mp_update->safi = safi;
2391
42
    return BGP_ATTR_PARSE_EOR;
2392
42
  }
2393
2394
115
  mp_update->afi = afi;
2395
115
  mp_update->safi = safi;
2396
115
  mp_update->nlri = stream_pnt(s);
2397
115
  mp_update->length = nlri_len;
2398
2399
115
  stream_forward_getp(s, nlri_len);
2400
2401
115
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2402
2403
115
  return BGP_ATTR_PARSE_PROCEED;
2404
157
#undef LEN_LEFT
2405
157
}
2406
2407
/* Multiprotocol unreachable parse */
2408
int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2409
       struct bgp_nlri *mp_withdraw)
2410
9
{
2411
9
  struct stream *s;
2412
9
  iana_afi_t pkt_afi;
2413
9
  afi_t afi;
2414
9
  iana_safi_t pkt_safi;
2415
9
  safi_t safi;
2416
9
  uint16_t withdraw_len;
2417
9
  struct peer *const peer = args->peer;
2418
9
  struct attr *const attr = args->attr;
2419
9
  const bgp_size_t length = args->length;
2420
2421
9
  s = peer->curr;
2422
2423
16
#define BGP_MP_UNREACH_MIN_SIZE 3
2424
9
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2425
1
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2426
2427
8
  pkt_afi = stream_getw(s);
2428
8
  pkt_safi = stream_getc(s);
2429
2430
  /* Convert AFI, SAFI to internal values, check. */
2431
8
  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
1
    if (bgp_debug_update(peer, NULL, NULL, 0))
2437
0
      zlog_debug(
2438
1
        "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2439
1
        peer->host, iana_afi2str(pkt_afi),
2440
1
        iana_safi2str(pkt_safi));
2441
1
    return BGP_ATTR_PARSE_ERROR;
2442
1
  }
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
8
}
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
0
    bgp_attr_set_lcommunity(attr, NULL);
2471
    /* Empty extcomm doesn't seem to be invalid per se */
2472
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2473
0
            args->total);
2474
0
  }
2475
2476
14
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2477
0
    goto large_community_ignore;
2478
2479
14
  bgp_attr_set_lcommunity(
2480
14
    attr, lcommunity_parse(stream_pnt(peer->curr), length));
2481
  /* XXX: fix ecommunity_parse to use stream API */
2482
14
  stream_forward_getp(peer->curr, length);
2483
2484
14
  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
12
  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
14
}
2495
2496
/* Extended Community attribute. */
2497
static enum bgp_attr_parse_ret
2498
bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
2499
109
{
2500
109
  struct peer *const peer = args->peer;
2501
109
  struct attr *const attr = args->attr;
2502
109
  const bgp_size_t length = args->length;
2503
109
  uint8_t sticky = 0;
2504
109
  bool proxy = false;
2505
109
  struct ecommunity *ecomm;
2506
2507
109
  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
109
  ecomm = ecommunity_parse(
2515
109
    stream_pnt(peer->curr), length,
2516
109
    CHECK_FLAG(peer->flags,
2517
109
         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2518
109
  bgp_attr_set_ecommunity(attr, ecomm);
2519
  /* XXX: fix ecommunity_parse to use stream API */
2520
109
  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
109
  if (!bgp_attr_get_ecommunity(attr))
2526
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2527
2
            args->total);
2528
2529
  /* Extract DF election preference and  mobility sequence number */
2530
107
  attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
2531
2532
  /* Extract MAC mobility sequence number, if any. */
2533
107
  attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
2534
107
  attr->sticky = sticky;
2535
2536
  /* Check if this is a Gateway MAC-IP advertisement */
2537
107
  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
107
  if (attr->default_gw)
2544
1
    attr->router_flag = 1;
2545
2546
  /* Check EVPN Neighbor advertisement flags, R-bit */
2547
107
  bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
2548
107
  if (proxy)
2549
10
    attr->es_flags |= ATTR_ES_PROXY_ADVERT;
2550
2551
  /* Extract the Rmac, if any */
2552
107
  if (bgp_attr_rmac(attr, &attr->rmac)) {
2553
4
    if (bgp_debug_update(peer, NULL, NULL, 1)
2554
4
        && bgp_mac_exist(&attr->rmac))
2555
0
      zlog_debug("%s: router mac %pEA is self mac", __func__,
2556
4
           &attr->rmac);
2557
4
  }
2558
2559
  /* Get the tunnel type from encap extended community */
2560
107
  bgp_attr_extcom_tunnel_type(attr,
2561
107
    (bgp_encap_types *)&attr->encap_tunneltype);
2562
2563
  /* Extract link bandwidth, if any. */
2564
107
  (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr),
2565
107
          &attr->link_bw);
2566
2567
107
  return BGP_ATTR_PARSE_PROCEED;
2568
109
}
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
25
{
2574
25
  struct peer *const peer = args->peer;
2575
25
  struct attr *const attr = args->attr;
2576
25
  const bgp_size_t length = args->length;
2577
25
  struct ecommunity *ipv6_ecomm = NULL;
2578
2579
25
  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
25
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2586
0
    goto ipv6_ext_community_ignore;
2587
2588
25
  ipv6_ecomm = ecommunity_parse_ipv6(
2589
25
    stream_pnt(peer->curr), length,
2590
25
    CHECK_FLAG(peer->flags,
2591
25
         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2592
25
  bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2593
2594
  /* XXX: fix ecommunity_parse to use stream API */
2595
25
  stream_forward_getp(peer->curr, length);
2596
2597
25
  if (!ipv6_ecomm)
2598
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2599
1
            args->total);
2600
2601
24
  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
25
}
2608
2609
/* Parse Tunnel Encap attribute in an UPDATE */
2610
static int bgp_attr_encap(struct bgp_attr_parser_args *args)
2611
8
{
2612
8
  uint16_t tunneltype = 0;
2613
8
  struct peer *const peer = args->peer;
2614
8
  struct attr *const attr = args->attr;
2615
8
  bgp_size_t length = args->length;
2616
8
  uint8_t type = args->type;
2617
8
  uint8_t flag = args->flags;
2618
2619
8
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)
2620
8
      || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
2621
1
    zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d",
2622
1
       flag);
2623
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2624
1
            args->total);
2625
1
  }
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
751
  while (length >= 4) {
2649
748
    uint16_t subtype = 0;
2650
748
    uint16_t sublength = 0;
2651
748
    struct bgp_attr_encap_subtlv *tlv;
2652
2653
748
    if (BGP_ATTR_ENCAP == type) {
2654
748
      subtype = stream_getc(BGP_INPUT(peer));
2655
748
      sublength = stream_getc(BGP_INPUT(peer));
2656
748
      length -= 2;
2657
748
#ifdef ENABLE_BGP_VNC
2658
748
    } 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
748
    if (sublength > length) {
2666
4
      zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2667
4
         sublength, length);
2668
4
      return bgp_attr_malformed(args,
2669
4
              BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2670
4
              args->total);
2671
4
    }
2672
2673
    /* alloc and copy sub-tlv */
2674
    /* TBD make sure these are freed when attributes are released */
2675
744
    tlv = XCALLOC(MTYPE_ENCAP_TLV,
2676
744
            sizeof(struct bgp_attr_encap_subtlv) + sublength);
2677
744
    tlv->type = subtype;
2678
744
    tlv->length = sublength;
2679
744
    stream_get(tlv->value, peer->curr, sublength);
2680
744
    length -= sublength;
2681
2682
    /* attach tlv to encap chain */
2683
744
    if (BGP_ATTR_ENCAP == type) {
2684
744
      struct bgp_attr_encap_subtlv *stlv_last;
2685
744
      for (stlv_last = attr->encap_subtlvs;
2686
49.8k
           stlv_last && stlv_last->next;
2687
49.0k
           stlv_last = stlv_last->next)
2688
49.0k
        ;
2689
744
      if (stlv_last) {
2690
737
        stlv_last->next = tlv;
2691
737
      } else {
2692
7
        attr->encap_subtlvs = tlv;
2693
7
      }
2694
744
#ifdef ENABLE_BGP_VNC
2695
744
    } 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
744
  }
2711
2712
3
  if (BGP_ATTR_ENCAP == type) {
2713
3
    attr->encap_tunneltype = tunneltype;
2714
3
  }
2715
2716
3
  if (length) {
2717
    /* spurious leftover data */
2718
1
    zlog_err("Tunnel Encap attribute length is bad: %d leftover octets",
2719
1
       length);
2720
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2721
1
            args->total);
2722
1
  }
2723
2724
2
  return 0;
2725
3
}
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
11
{
2734
11
  struct peer *const peer = args->peer;
2735
11
  struct attr *const attr = args->attr;
2736
11
  uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2737
11
    transposition_len, transposition_offset;
2738
11
  uint16_t length;
2739
11
  size_t headersz = sizeof(type) + sizeof(length);
2740
2741
11
  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
11
  type = stream_getc(peer->curr);
2751
11
  length = stream_getw(peer->curr);
2752
2753
11
  if (STREAM_READABLE(peer->curr) < length) {
2754
1
    flog_err(
2755
1
      EC_BGP_ATTR_LEN,
2756
1
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2757
1
      length, STREAM_READABLE(peer->curr));
2758
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2759
1
            args->total);
2760
1
  }
2761
2762
10
  if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2763
3
    flog_err(
2764
3
      EC_BGP_ATTR_LEN,
2765
3
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2766
3
      BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2767
3
      length);
2768
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2769
3
            args->total);
2770
3
  }
2771
2772
7
  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
5
  else {
2810
5
    if (bgp_debug_update(peer, NULL, NULL, 1))
2811
0
      zlog_debug(
2812
5
        "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2813
5
        peer->host, type);
2814
2815
5
    stream_forward_getp(peer->curr, length);
2816
5
  }
2817
2818
7
  return BGP_ATTR_PARSE_PROCEED;
2819
7
}
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
23
{
2827
23
  struct peer *const peer = args->peer;
2828
23
  struct attr *const attr = args->attr;
2829
23
  struct in6_addr ipv6_sid;
2830
23
  uint8_t type, sid_flags;
2831
23
  uint16_t length, endpoint_behavior;
2832
23
  size_t headersz = sizeof(type) + sizeof(length);
2833
23
  enum bgp_attr_parse_ret err;
2834
2835
23
  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
23
  type = stream_getc(peer->curr);
2845
23
  length = stream_getw(peer->curr);
2846
2847
23
  if (STREAM_READABLE(peer->curr) < length) {
2848
1
    flog_err(
2849
1
      EC_BGP_ATTR_LEN,
2850
1
      "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2851
1
      length, STREAM_READABLE(peer->curr));
2852
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2853
1
            args->total);
2854
1
  }
2855
2856
22
  if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
2857
14
    if (STREAM_READABLE(peer->curr) <
2858
14
        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
14
    stream_getc(peer->curr);
2869
14
    stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2870
14
    sid_flags = stream_getc(peer->curr);
2871
14
    endpoint_behavior = stream_getw(peer->curr);
2872
14
    stream_getc(peer->curr);
2873
2874
    /* Log SRv6 Service Sub-TLV */
2875
14
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
2876
0
      zlog_debug(
2877
14
        "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2878
14
        __func__, &ipv6_sid, sid_flags,
2879
14
        endpoint_behavior);
2880
2881
    /* Configure from Info */
2882
14
    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
13
    attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2889
13
             sizeof(struct bgp_attr_srv6_l3vpn));
2890
13
    sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
2891
13
    attr->srv6_l3vpn->sid_flags = sid_flags;
2892
13
    attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
2893
13
    attr->srv6_l3vpn->loc_block_len = 0;
2894
13
    attr->srv6_l3vpn->loc_node_len = 0;
2895
13
    attr->srv6_l3vpn->func_len = 0;
2896
13
    attr->srv6_l3vpn->arg_len = 0;
2897
13
    attr->srv6_l3vpn->transposition_len = 0;
2898
13
    attr->srv6_l3vpn->transposition_offset = 0;
2899
2900
    // Sub-Sub-TLV found
2901
13
    if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2902
11
      err = bgp_attr_srv6_service_data(args);
2903
2904
11
      if (err != BGP_ATTR_PARSE_PROCEED)
2905
4
        return err;
2906
11
    }
2907
2908
9
    attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
2909
9
  }
2910
2911
  /* Placeholder code for unsupported type */
2912
8
  else {
2913
8
    if (bgp_debug_update(peer, NULL, NULL, 1))
2914
0
      zlog_debug(
2915
8
        "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2916
8
        peer->host, type);
2917
2918
8
    stream_forward_getp(peer->curr, length);
2919
8
  }
2920
2921
17
  return BGP_ATTR_PARSE_PROCEED;
2922
22
}
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
433
{
2932
433
  struct peer *const peer = args->peer;
2933
433
  struct attr *const attr = args->attr;
2934
433
  uint32_t label_index;
2935
433
  struct in6_addr ipv6_sid;
2936
433
  uint32_t srgb_base;
2937
433
  uint32_t srgb_range;
2938
433
  int srgb_count;
2939
433
  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
433
  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
433
  if (type == BGP_PREFIX_SID_LABEL_INDEX) {
2955
4
    if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
2956
3
      flog_err(EC_BGP_ATTR_LEN,
2957
3
         "Prefix SID label index length is %hu instead of %u",
2958
3
         length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
2959
3
      return bgp_attr_malformed(args,
2960
3
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2961
3
              args->total);
2962
3
    }
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
429
  } else if (type == BGP_PREFIX_SID_IPV6) {
2978
0
    if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
2979
0
      flog_err(EC_BGP_ATTR_LEN,
2980
0
         "Prefix SID IPv6 length is %hu instead of %u",
2981
0
         length, BGP_PREFIX_SID_IPV6_LENGTH);
2982
0
      return bgp_attr_malformed(args,
2983
0
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2984
0
              args->total);
2985
0
    }
2986
2987
    /* Ignore reserved */
2988
0
    stream_getc(peer->curr);
2989
0
    stream_getw(peer->curr);
2990
2991
0
    stream_get(&ipv6_sid, peer->curr, 16);
2992
429
  } 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
5
    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
5
    stream_getw(peer->curr);
3023
5
    length -= 2;
3024
5
    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
3
    srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
3035
3036
224
    for (int i = 0; i < srgb_count; i++) {
3037
221
      stream_get(&srgb_base, peer->curr, 3);
3038
221
      stream_get(&srgb_range, peer->curr, 3);
3039
221
    }
3040
424
  } else if (type == BGP_PREFIX_SID_VPN_SID) {
3041
0
    if (length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
3042
0
      flog_err(EC_BGP_ATTR_LEN,
3043
0
         "Prefix SID VPN SID length is %hu instead of %u",
3044
0
         length, BGP_PREFIX_SID_VPN_SID_LENGTH);
3045
0
      return bgp_attr_malformed(args,
3046
0
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3047
0
              args->total);
3048
0
    }
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
424
  } else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
3076
25
    if (STREAM_READABLE(peer->curr) < 1) {
3077
2
      flog_err(
3078
2
        EC_BGP_ATTR_LEN,
3079
2
        "Prefix SID SRV6 L3 Service not enough data left, it must be at least 1 byte");
3080
2
      return bgp_attr_malformed(
3081
2
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3082
2
        args->total);
3083
2
    }
3084
    /* ignore reserved */
3085
23
    stream_getc(peer->curr);
3086
3087
23
    return bgp_attr_srv6_service(args);
3088
25
  }
3089
  /* Placeholder code for Unsupported TLV */
3090
399
  else {
3091
399
    if (bgp_debug_update(peer, NULL, NULL, 1))
3092
0
      zlog_debug(
3093
399
        "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3094
399
        peer->host, type);
3095
3096
399
    stream_forward_getp(peer->curr, length);
3097
399
  }
3098
3099
403
  return BGP_ATTR_PARSE_PROCEED;
3100
433
}
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
39
{
3107
39
  struct peer *const peer = args->peer;
3108
39
  struct attr *const attr = args->attr;
3109
39
  enum bgp_attr_parse_ret ret;
3110
3111
39
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3112
3113
39
  uint8_t type;
3114
39
  uint16_t length;
3115
39
  size_t headersz = sizeof(type) + sizeof(length);
3116
39
  size_t psid_parsed_length = 0;
3117
3118
456
  while (STREAM_READABLE(peer->curr) > 0
3119
456
         && psid_parsed_length < args->length) {
3120
3121
452
    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
451
    type = stream_getc(peer->curr);
3132
451
    length = stream_getw(peer->curr);
3133
3134
451
    if (STREAM_READABLE(peer->curr) < length) {
3135
18
      flog_err(
3136
18
        EC_BGP_ATTR_LEN,
3137
18
        "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3138
18
        length, STREAM_READABLE(peer->curr));
3139
18
      return bgp_attr_malformed(args,
3140
18
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3141
18
              args->total);
3142
18
    }
3143
3144
433
    ret = bgp_attr_psid_sub(type, length, args);
3145
3146
433
    if (ret != BGP_ATTR_PARSE_PROCEED)
3147
13
      return ret;
3148
3149
420
    psid_parsed_length += length + headersz;
3150
3151
420
    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
420
  }
3161
3162
4
  return BGP_ATTR_PARSE_PROCEED;
3163
39
}
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
0
{
3171
0
  struct peer *const peer = args->peer;
3172
0
  struct attr *const attr = args->attr;
3173
0
  const bgp_size_t length = args->length;
3174
0
  uint8_t tnl_type;
3175
0
  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
0
  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
0
  stream_getc(peer->curr); /* Flags */
3187
0
  tnl_type = stream_getc(peer->curr);
3188
0
  if (tnl_type > PMSI_TNLTYPE_MAX) {
3189
0
    flog_err(EC_BGP_ATTR_PMSI_TYPE,
3190
0
       "Invalid PMSI tunnel attribute type %d", tnl_type);
3191
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
3192
0
            args->total);
3193
0
  }
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
3
{
3218
3
  struct peer *const peer = args->peer;
3219
3
  struct attr *const attr = args->attr;
3220
3
  const bgp_size_t length = args->length;
3221
3
  uint8_t *s = stream_pnt(peer->curr);
3222
3
  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
3
  if (peer->sort == BGP_PEER_EBGP &&
3234
3
      !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
3235
3
    zlog_warn(
3236
3
      "%pBP received AIGP attribute, but eBGP peer do not support it",
3237
3
      peer);
3238
3
    goto aigp_ignore;
3239
3
  }
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
3
aigp_ignore:
3252
3
  stream_forward_getp(peer->curr, length);
3253
3254
3
  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
1
{
3260
1
  struct peer *const peer = args->peer;
3261
1
  struct attr *const attr = args->attr;
3262
1
  const bgp_size_t length = args->length;
3263
3264
  /* Length check. */
3265
1
  if (length != 4) {
3266
1
    flog_err(EC_BGP_ATTR_LEN, "OTC attribute length isn't 4 [%u]",
3267
1
       length);
3268
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3269
1
            args->total);
3270
1
  }
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
305
{
3296
305
  bgp_size_t total = args->total;
3297
305
  struct transit *transit;
3298
305
  struct peer *const peer = args->peer;
3299
305
  struct attr *const attr = args->attr;
3300
305
  uint8_t *const startp = args->startp;
3301
305
  const uint8_t type = args->type;
3302
305
  const uint8_t flag = args->flags;
3303
305
  const bgp_size_t length = args->length;
3304
3305
305
  if (bgp_debug_update(peer, NULL, NULL, 1))
3306
0
    zlog_debug(
3307
305
      "%s Unknown attribute is received (type %d, length %d)",
3308
305
      peer->host, type, length);
3309
3310
  /* Forward read pointer of input stream. */
3311
305
  stream_forward_getp(peer->curr, length);
3312
3313
305
  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
305
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
3321
41
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR,
3322
41
            args->total);
3323
41
  }
3324
3325
  /* Unrecognized non-transitive optional attributes must be quietly
3326
     ignored and not passed along to other BGP peers. */
3327
264
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3328
142
    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
122
  SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3335
3336
  /* Store transitive attribute to the end of attr->transit. */
3337
122
  transit = bgp_attr_get_transit(attr);
3338
122
  if (!transit)
3339
90
    transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
3340
3341
122
  transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3342
122
        transit->length + total);
3343
3344
122
  memcpy(transit->val + transit->length, startp, total);
3345
122
  transit->length += total;
3346
122
  bgp_attr_set_transit(attr, transit);
3347
3348
122
  return BGP_ATTR_PARSE_PROCEED;
3349
264
}
3350
3351
/* Well-known attribute check. */
3352
static int bgp_attr_check(struct peer *peer, struct attr *attr)
3353
128
{
3354
128
  uint8_t type = 0;
3355
3356
  /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3357
   * empty UPDATE.  */
3358
128
  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
128
  if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3367
128
       CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
3368
4
    return BGP_ATTR_PARSE_PROCEED;
3369
3370
124
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3371
37
    type = BGP_ATTR_ORIGIN;
3372
3373
124
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3374
37
    type = BGP_ATTR_AS_PATH;
3375
3376
  /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present
3377
   * and
3378
   * NLRI is empty. We can't easily check NLRI empty here though.
3379
   */
3380
124
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3381
124
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3382
27
    type = BGP_ATTR_NEXT_HOP;
3383
3384
124
  if (peer->sort == BGP_PEER_IBGP
3385
124
      && !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
124
  if (type) {
3392
37
    flog_warn(EC_BGP_MISSING_ATTRIBUTE,
3393
37
        "%s Missing well-known attribute %s.", peer->host,
3394
37
        lookup_msg(attr_str, type, NULL));
3395
37
    return BGP_ATTR_PARSE_WITHDRAW;
3396
37
  }
3397
87
  return BGP_ATTR_PARSE_PROCEED;
3398
124
}
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
462
{
3407
462
  enum bgp_attr_parse_ret ret;
3408
462
  uint8_t flag = 0;
3409
462
  uint8_t type = 0;
3410
462
  bgp_size_t length;
3411
462
  uint8_t *startp, *endp;
3412
462
  uint8_t *attr_endp;
3413
462
  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
462
  struct aspath *as4_path = NULL;
3418
462
  as_t as4_aggregator = 0;
3419
462
  struct in_addr as4_aggregator_addr = {.s_addr = 0};
3420
462
  struct transit *transit;
3421
3422
  /* Initialize bitmap. */
3423
462
  memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3424
3425
  /* End pointer of BGP attribute. */
3426
462
  endp = BGP_INPUT_PNT(peer) + size;
3427
3428
  /* Get attributes to the end of attribute length. */
3429
1.34k
  while (BGP_INPUT_PNT(peer) < endp) {
3430
    /* Check remaining length check.*/
3431
1.21k
    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.21k
    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.21k
    flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3452
1.21k
    type = stream_getc(BGP_INPUT(peer));
3453
3454
    /* Check whether Extended-Length applies and is in bounds */
3455
1.21k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3456
1.21k
        && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
3457
3
      flog_warn(
3458
3
        EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
3459
3
        "%s: Extended length set, but just %lu bytes of attr header",
3460
3
        peer->host,
3461
3
        (unsigned long)(endp
3462
3
            - stream_pnt(BGP_INPUT(peer))));
3463
3464
3
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3465
3
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3466
3
      ret = BGP_ATTR_PARSE_ERROR;
3467
3
      goto done;
3468
3
    }
3469
3470
    /* Check extended attribue length bit. */
3471
1.20k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3472
445
      length = stream_getw(BGP_INPUT(peer));
3473
762
    else
3474
762
      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.20k
    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.20k
    SET_BITMAP(seen, type);
3496
3497
    /* Overflow check. */
3498
1.20k
    attr_endp = BGP_INPUT_PNT(peer) + length;
3499
3500
1.20k
    if (attr_endp > endp) {
3501
112
      flog_warn(
3502
112
        EC_BGP_ATTRIBUTE_TOO_LARGE,
3503
112
        "%s: BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p",
3504
112
        peer->host, type, length, size, attr_endp,
3505
112
        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
112
      unsigned char ndata[peer->max_packet_size];
3527
112
      memset(ndata, 0x00, sizeof(ndata));
3528
112
      size_t lfl =
3529
112
        CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3530
      /* Rewind to end of flag field */
3531
112
      stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
3532
      /* Type */
3533
112
      stream_get(&ndata[0], BGP_INPUT(peer), 1);
3534
      /* Length */
3535
112
      stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3536
      /* Value */
3537
112
      size_t atl = attr_endp - startp;
3538
112
      size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3539
112
      stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3540
3541
112
      bgp_notify_send_with_data(
3542
112
        peer, BGP_NOTIFY_UPDATE_ERR,
3543
112
        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3544
112
        ndl + lfl + 1);
3545
3546
112
      ret = BGP_ATTR_PARSE_ERROR;
3547
112
      goto done;
3548
112
    }
3549
3550
1.08k
    struct bgp_attr_parser_args attr_args = {
3551
1.08k
      .peer = peer,
3552
1.08k
      .length = length,
3553
1.08k
      .attr = attr,
3554
1.08k
      .type = type,
3555
1.08k
      .flags = flag,
3556
1.08k
      .startp = startp,
3557
1.08k
      .total = attr_endp - startp,
3558
1.08k
    };
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.08k
    if (bgp_attr_flag_invalid(&attr_args)) {
3567
42
      ret = bgp_attr_malformed(
3568
42
        &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3569
42
        attr_args.total);
3570
42
      if (ret == BGP_ATTR_PARSE_PROCEED)
3571
4
        continue;
3572
38
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3573
38
      goto done;
3574
42
    }
3575
3576
    /* OK check attribute and store it's value. */
3577
1.04k
    switch (type) {
3578
90
    case BGP_ATTR_ORIGIN:
3579
90
      ret = bgp_attr_origin(&attr_args);
3580
90
      break;
3581
112
    case BGP_ATTR_AS_PATH:
3582
112
      ret = bgp_attr_aspath(&attr_args);
3583
112
      break;
3584
41
    case BGP_ATTR_AS4_PATH:
3585
41
      ret = bgp_attr_as4_path(&attr_args, &as4_path);
3586
41
      break;
3587
52
    case BGP_ATTR_NEXT_HOP:
3588
52
      ret = bgp_attr_nexthop(&attr_args);
3589
52
      break;
3590
4
    case BGP_ATTR_MULTI_EXIT_DISC:
3591
4
      ret = bgp_attr_med(&attr_args);
3592
4
      break;
3593
4
    case BGP_ATTR_LOCAL_PREF:
3594
4
      ret = bgp_attr_local_pref(&attr_args);
3595
4
      break;
3596
7
    case BGP_ATTR_ATOMIC_AGGREGATE:
3597
7
      ret = bgp_attr_atomic(&attr_args);
3598
7
      break;
3599
0
    case BGP_ATTR_AGGREGATOR:
3600
0
      ret = bgp_attr_aggregator(&attr_args);
3601
0
      break;
3602
0
    case BGP_ATTR_AS4_AGGREGATOR:
3603
0
      ret = bgp_attr_as4_aggregator(&attr_args,
3604
0
                  &as4_aggregator,
3605
0
                  &as4_aggregator_addr);
3606
0
      break;
3607
34
    case BGP_ATTR_COMMUNITIES:
3608
34
      ret = bgp_attr_community(&attr_args);
3609
34
      break;
3610
14
    case BGP_ATTR_LARGE_COMMUNITIES:
3611
14
      ret = bgp_attr_large_community(&attr_args);
3612
14
      break;
3613
2
    case BGP_ATTR_ORIGINATOR_ID:
3614
2
      ret = bgp_attr_originator_id(&attr_args);
3615
2
      break;
3616
24
    case BGP_ATTR_CLUSTER_LIST:
3617
24
      ret = bgp_attr_cluster_list(&attr_args);
3618
24
      break;
3619
163
    case BGP_ATTR_MP_REACH_NLRI:
3620
163
      ret = bgp_mp_reach_parse(&attr_args, mp_update);
3621
163
      break;
3622
9
    case BGP_ATTR_MP_UNREACH_NLRI:
3623
9
      ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3624
9
      break;
3625
109
    case BGP_ATTR_EXT_COMMUNITIES:
3626
109
      ret = bgp_attr_ext_communities(&attr_args);
3627
109
      break;
3628
#ifdef ENABLE_BGP_VNC_ATTR
3629
    case BGP_ATTR_VNC:
3630
#endif
3631
8
    case BGP_ATTR_ENCAP:
3632
8
      ret = bgp_attr_encap(&attr_args);
3633
8
      break;
3634
39
    case BGP_ATTR_PREFIX_SID:
3635
39
      ret = bgp_attr_prefix_sid(&attr_args);
3636
39
      break;
3637
0
    case BGP_ATTR_PMSI_TUNNEL:
3638
0
      ret = bgp_attr_pmsi_tunnel(&attr_args);
3639
0
      break;
3640
25
    case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3641
25
      ret = bgp_attr_ipv6_ext_communities(&attr_args);
3642
25
      break;
3643
1
    case BGP_ATTR_OTC:
3644
1
      ret = bgp_attr_otc(&attr_args);
3645
1
      break;
3646
3
    case BGP_ATTR_AIGP:
3647
3
      ret = bgp_attr_aigp(&attr_args);
3648
3
      break;
3649
305
    default:
3650
305
      ret = bgp_attr_unknown(&attr_args);
3651
305
      break;
3652
1.04k
    }
3653
3654
1.04k
    if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3655
66
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3656
66
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3657
66
      ret = BGP_ATTR_PARSE_ERROR;
3658
66
      goto done;
3659
66
    }
3660
3661
980
    if (ret == BGP_ATTR_PARSE_EOR) {
3662
42
      goto done;
3663
42
    }
3664
3665
938
    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
936
    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
878
    if (BGP_INPUT_PNT(peer) != attr_endp) {
3682
3
      flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
3683
3
          "%s: BGP attribute %s, fetch error",
3684
3
          peer->host, lookup_msg(attr_str, type, NULL));
3685
3
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3686
3
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3687
3
      ret = BGP_ATTR_PARSE_ERROR;
3688
3
      goto done;
3689
3
    }
3690
878
  }
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
128
  if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3701
128
    attr->label_index = BGP_INVALID_LABEL_INDEX;
3702
3703
  /* Check final read pointer is same as end pointer. */
3704
128
  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
128
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3729
128
      && !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
128
  ret = bgp_attr_check(peer, attr);
3738
128
  if (ret < 0)
3739
37
    goto done;
3740
3741
  /*
3742
   * At this place we can see whether we got AS4_PATH and/or
3743
   * AS4_AGGREGATOR from a 16Bit peer and act accordingly.
3744
   * We can not do this before we've read all attributes because
3745
   * the as4 handling does not say whether AS4_PATH has to be sent
3746
   * after AS_PATH or not - and when AS4_AGGREGATOR will be send
3747
   * in relationship to AGGREGATOR.
3748
   * So, to be defensive, we are not relying on any order and read
3749
   * all attributes first, including these 32bit ones, and now,
3750
   * afterwards, we look what and if something is to be done for as4.
3751
   *
3752
   * It is possible to not have AS_PATH, e.g. GR EoR and sole
3753
   * MP_UNREACH_NLRI.
3754
   */
3755
  /* actually... this doesn't ever return failure currently, but
3756
   * better safe than sorry */
3757
91
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3758
91
      && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3759
89
          &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
91
  if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3771
89
    ret = bgp_attr_aspath_check(peer, attr);
3772
89
    if (ret != BGP_ATTR_PARSE_PROCEED)
3773
0
      goto done;
3774
89
  }
3775
3776
91
  ret = BGP_ATTR_PARSE_PROCEED;
3777
462
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
462
  aspath_unintern(&as4_path);
3791
3792
462
  transit = bgp_attr_get_transit(attr);
3793
462
  if (ret != BGP_ATTR_PARSE_ERROR) {
3794
    /* Finally intern unknown attribute. */
3795
266
    if (transit)
3796
73
      bgp_attr_set_transit(attr, transit_intern(transit));
3797
266
    if (attr->encap_subtlvs)
3798
5
      attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3799
5
                 ENCAP_SUBTLV_TYPE);
3800
266
#ifdef ENABLE_BGP_VNC
3801
266
    struct bgp_attr_encap_subtlv *vnc_subtlvs =
3802
266
      bgp_attr_get_vnc_subtlvs(attr);
3803
3804
266
    if (vnc_subtlvs)
3805
0
      bgp_attr_set_vnc_subtlvs(
3806
0
        attr,
3807
0
        encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
3808
266
#endif
3809
266
  } else {
3810
196
    if (transit) {
3811
17
      transit_free(transit);
3812
17
      bgp_attr_set_transit(attr, NULL);
3813
17
    }
3814
3815
196
    bgp_attr_flush_encap(attr);
3816
196
  };
3817
3818
  /* Sanity checks */
3819
462
  transit = bgp_attr_get_transit(attr);
3820
462
  if (transit)
3821
73
    assert(transit->refcnt > 0);
3822
462
  if (attr->encap_subtlvs)
3823
5
    assert(attr->encap_subtlvs->refcnt > 0);
3824
462
#ifdef ENABLE_BGP_VNC
3825
462
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
3826
462
    bgp_attr_get_vnc_subtlvs(attr);
3827
3828
462
  if (vnc_subtlvs)
3829
0
    assert(vnc_subtlvs->refcnt > 0);
3830
462
#endif
3831
3832
462
  return ret;
3833
462
}
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
107
{
3841
107
  struct ecommunity *ecom;
3842
107
  uint32_t i;
3843
3844
107
  if (!attr)
3845
0
    return;
3846
3847
107
  ecom = bgp_attr_get_ecommunity(attr);
3848
107
  if (!ecom || !ecom->size)
3849
0
    return;
3850
3851
10.3k
  for (i = 0; i < ecom->size; i++) {
3852
10.2k
    uint8_t *pnt;
3853
10.2k
    uint8_t type, sub_type;
3854
3855
10.2k
    pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3856
10.2k
    type = pnt[0];
3857
10.2k
    sub_type = pnt[1];
3858
10.2k
    if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3859
10.2k
          sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3860
10.2k
      continue;
3861
6
    *tunnel_type = ((pnt[6] << 8) | pnt[7]);
3862
6
    return;
3863
10.2k
  }
3864
3865
101
  return;
3866
107
}
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
3
{
5182
3
  bool discard = peer->discard_attrs[type];
5183
3
  bool withdraw = peer->withdraw_attrs[type];
5184
5185
3
  if (bgp_debug_update(peer, NULL, NULL, 1) && (discard || withdraw))
5186
0
    zlog_debug("%pBP: Ignoring attribute %s (%s)", peer,
5187
3
         lookup_msg(attr_str, type, NULL),
5188
3
         withdraw ? "treat-as-withdraw" : "discard");
5189
5190
3
  return withdraw ? BGP_ATTR_PARSE_WITHDRAW : BGP_ATTR_PARSE_PROCEED;
5191
3
}