Coverage Report

Created: 2026-03-21 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_attr.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* BGP attributes management routines.
3
 * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
4
 */
5
6
#include <zebra.h>
7
8
#include "linklist.h"
9
#include "prefix.h"
10
#include "memory.h"
11
#include "vector.h"
12
#include "stream.h"
13
#include "log.h"
14
#include "hash.h"
15
#include "jhash.h"
16
#include "queue.h"
17
#include "table.h"
18
#include "filter.h"
19
#include "command.h"
20
#include "srv6.h"
21
#include "frrstr.h"
22
23
#include "bgpd/bgpd.h"
24
#include "bgpd/bgp_attr.h"
25
#include "bgpd/bgp_route.h"
26
#include "bgpd/bgp_aspath.h"
27
#include "bgpd/bgp_community.h"
28
#include "bgpd/bgp_debug.h"
29
#include "bgpd/bgp_errors.h"
30
#include "bgpd/bgp_label.h"
31
#include "bgpd/bgp_packet.h"
32
#include "bgpd/bgp_ecommunity.h"
33
#include "bgpd/bgp_lcommunity.h"
34
#include "bgpd/bgp_updgrp.h"
35
#include "bgpd/bgp_encap_types.h"
36
#ifdef ENABLE_BGP_VNC
37
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
38
#include "bgp_encap_types.h"
39
#include "bgp_vnc_types.h"
40
#endif
41
#include "bgp_evpn.h"
42
#include "bgp_flowspec_private.h"
43
#include "bgp_mac.h"
44
45
/* Attribute strings for logging. */
46
static const struct message attr_str[] = {
47
  {BGP_ATTR_ORIGIN, "ORIGIN"},
48
  {BGP_ATTR_AS_PATH, "AS_PATH"},
49
  {BGP_ATTR_NEXT_HOP, "NEXT_HOP"},
50
  {BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC"},
51
  {BGP_ATTR_LOCAL_PREF, "LOCAL_PREF"},
52
  {BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE"},
53
  {BGP_ATTR_AGGREGATOR, "AGGREGATOR"},
54
  {BGP_ATTR_COMMUNITIES, "COMMUNITY"},
55
  {BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID"},
56
  {BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST"},
57
  {BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI"},
58
  {BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI"},
59
  {BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES"},
60
  {BGP_ATTR_AS4_PATH, "AS4_PATH"},
61
  {BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"},
62
  {BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
63
  {BGP_ATTR_ENCAP, "ENCAP"},
64
  {BGP_ATTR_OTC, "OTC"},
65
#ifdef ENABLE_BGP_VNC_ATTR
66
  {BGP_ATTR_VNC, "VNC"},
67
#endif
68
  {BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
69
  {BGP_ATTR_PREFIX_SID, "PREFIX_SID"},
70
  {BGP_ATTR_IPV6_EXT_COMMUNITIES, "IPV6_EXT_COMMUNITIES"},
71
  {BGP_ATTR_AIGP, "AIGP"},
72
  {0}};
73
74
static const struct message attr_flag_str[] = {
75
  {BGP_ATTR_FLAG_OPTIONAL, "Optional"},
76
  {BGP_ATTR_FLAG_TRANS, "Transitive"},
77
  {BGP_ATTR_FLAG_PARTIAL, "Partial"},
78
  /* bgp_attr_flags_diagnose() relies on this bit being last in
79
     this list */
80
  {BGP_ATTR_FLAG_EXTLEN, "Extended Length"},
81
  {0}};
82
83
static struct hash *cluster_hash;
84
85
static void *cluster_hash_alloc(void *p)
86
19
{
87
19
  const struct cluster_list *val = (const struct cluster_list *)p;
88
19
  struct cluster_list *cluster;
89
90
19
  cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list));
91
19
  cluster->length = val->length;
92
93
19
  if (cluster->length) {
94
19
    cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length);
95
19
    memcpy(cluster->list, val->list, val->length);
96
19
  } else
97
0
    cluster->list = NULL;
98
99
19
  cluster->refcnt = 0;
100
101
19
  return cluster;
102
19
}
103
104
/* Cluster list related functions. */
105
static struct cluster_list *cluster_parse(struct in_addr *pnt, int length)
106
19
{
107
19
  struct cluster_list tmp = {};
108
19
  struct cluster_list *cluster;
109
110
19
  tmp.length = length;
111
19
  tmp.list = length == 0 ? NULL : pnt;
112
113
19
  cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc);
114
19
  cluster->refcnt++;
115
19
  return cluster;
116
19
}
117
118
bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
119
1
{
120
1
  int i;
121
122
5
  for (i = 0; i < cluster->length / 4; i++)
123
4
    if (cluster->list[i].s_addr == originator.s_addr)
124
0
      return true;
125
1
  return false;
126
1
}
127
128
static unsigned int cluster_hash_key_make(const void *p)
129
38
{
130
38
  const struct cluster_list *cluster = p;
131
132
38
  return jhash(cluster->list, cluster->length, 0);
133
38
}
134
135
static bool cluster_hash_cmp(const void *p1, const void *p2)
136
19
{
137
19
  const struct cluster_list *cluster1 = p1;
138
19
  const struct cluster_list *cluster2 = p2;
139
140
19
  if (cluster1->list == cluster2->list)
141
19
    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
19
{
154
19
  XFREE(MTYPE_CLUSTER_VAL, cluster->list);
155
19
  XFREE(MTYPE_CLUSTER, cluster);
156
19
}
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
19
{
170
19
  if ((*cluster)->refcnt)
171
19
    (*cluster)->refcnt--;
172
173
19
  if ((*cluster)->refcnt == 0) {
174
19
    void *p = hash_release(cluster_hash, *cluster);
175
19
    assert(p == *cluster);
176
19
    cluster_free(*cluster);
177
19
    *cluster = NULL;
178
19
  }
179
19
}
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
8
{
223
8
  struct bgp_attr_encap_subtlv *next;
224
561
  while (p) {
225
553
    next = p->next;
226
553
    p->next = NULL;
227
553
    XFREE(MTYPE_ENCAP_TLV, p);
228
553
    p = next;
229
553
  }
230
8
}
231
232
void bgp_attr_flush_encap(struct attr *attr)
233
171
{
234
171
  if (!attr)
235
0
    return;
236
237
171
  if (attr->encap_subtlvs) {
238
1
    encap_free(attr->encap_subtlvs);
239
1
    attr->encap_subtlvs = NULL;
240
1
  }
241
171
#ifdef ENABLE_BGP_VNC
242
171
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
243
171
    bgp_attr_get_vnc_subtlvs(attr);
244
245
171
  if (vnc_subtlvs) {
246
0
    encap_free(vnc_subtlvs);
247
0
    bgp_attr_set_vnc_subtlvs(attr, NULL);
248
0
  }
249
171
#endif
250
171
}
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
7
{
263
7
  const struct bgp_attr_encap_subtlv *p;
264
7
  const struct bgp_attr_encap_subtlv *q;
265
266
7
  if (h1 == h2)
267
7
    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
7
{
300
  /* Encap structure is already allocated.  */
301
7
  return p;
302
7
}
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
7
{
314
7
  struct bgp_attr_encap_subtlv *find;
315
7
  struct hash *hash = encap_hash;
316
7
#ifdef ENABLE_BGP_VNC
317
7
  if (type == VNC_SUBTLV_TYPE)
318
0
    hash = vnc_hash;
319
7
#endif
320
321
7
  find = hash_get(hash, encap, encap_hash_alloc);
322
7
  if (find != encap)
323
0
    encap_free(encap);
324
7
  find->refcnt++;
325
326
7
  return find;
327
7
}
328
329
static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
330
         encap_subtlv_type type)
331
7
{
332
7
  struct bgp_attr_encap_subtlv *encap = *encapp;
333
7
  if (encap->refcnt)
334
7
    encap->refcnt--;
335
336
7
  if (encap->refcnt == 0) {
337
7
    struct hash *hash = encap_hash;
338
7
#ifdef ENABLE_BGP_VNC
339
7
    if (type == VNC_SUBTLV_TYPE)
340
0
      hash = vnc_hash;
341
7
#endif
342
7
    hash_release(hash, encap);
343
7
    encap_free(encap);
344
7
    *encapp = NULL;
345
7
  }
346
7
}
347
348
static unsigned int encap_hash_key_make(const void *p)
349
14
{
350
14
  const struct bgp_attr_encap_subtlv *encap = p;
351
352
14
  return jhash(encap->value, encap->length, 0);
353
14
}
354
355
static bool encap_hash_cmp(const void *p1, const void *p2)
356
7
{
357
7
  return encap_same((const struct bgp_attr_encap_subtlv *)p1,
358
7
        (const struct bgp_attr_encap_subtlv *)p2);
359
7
}
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
61
{
397
61
  XFREE(MTYPE_TRANSIT_VAL, transit->val);
398
61
  XFREE(MTYPE_TRANSIT, transit);
399
61
}
400
401
static void *transit_hash_alloc(void *p)
402
50
{
403
  /* Transit structure is already allocated.  */
404
50
  return p;
405
50
}
406
407
static struct transit *transit_intern(struct transit *transit)
408
50
{
409
50
  struct transit *find;
410
411
50
  find = hash_get(transit_hash, transit, transit_hash_alloc);
412
50
  if (find != transit)
413
0
    transit_free(transit);
414
50
  find->refcnt++;
415
416
50
  return find;
417
50
}
418
419
static void transit_unintern(struct transit **transit)
420
50
{
421
50
  if ((*transit)->refcnt)
422
50
    (*transit)->refcnt--;
423
424
50
  if ((*transit)->refcnt == 0) {
425
50
    hash_release(transit_hash, *transit);
426
50
    transit_free(*transit);
427
50
    *transit = NULL;
428
50
  }
429
50
}
430
431
static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length,
432
           uint64_t *aigp)
433
0
{
434
0
  uint8_t *data = pnt;
435
0
  uint8_t tlv_type;
436
0
  uint16_t tlv_length;
437
438
0
  while (length) {
439
0
    tlv_type = *data;
440
0
    ptr_get_be16(data + 1, &tlv_length);
441
0
    (void)data;
442
443
    /* The value field of the AIGP TLV is always 8 octets
444
     * long and its value is interpreted as an unsigned 64-bit
445
     * integer.
446
     */
447
0
    if (tlv_type == BGP_AIGP_TLV_METRIC) {
448
0
      (void)ptr_get_be64(data + 3, aigp);
449
450
      /* If an AIGP attribute is received and its first AIGP
451
       * TLV contains the maximum value 0xffffffffffffffff,
452
       * the attribute SHOULD be considered to be malformed
453
       * and SHOULD be discarded as specified in this section.
454
       */
455
0
      if (*aigp == BGP_AIGP_TLV_METRIC_MAX) {
456
0
        zlog_err("Bad AIGP TLV (%s) length: %llu",
457
0
           BGP_AIGP_TLV_METRIC_DESC,
458
0
           BGP_AIGP_TLV_METRIC_MAX);
459
0
        return false;
460
0
      }
461
462
0
      return true;
463
0
    }
464
465
0
    data += tlv_length;
466
0
    length -= tlv_length;
467
0
  }
468
469
0
  return false;
470
0
}
471
472
static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
473
0
{
474
0
  uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
475
476
0
  if (bpi->nexthop)
477
0
    return aigp + bpi->nexthop->metric;
478
0
  else
479
0
    return aigp;
480
0
}
481
482
static void stream_put_bgp_aigp_tlv_metric(struct stream *s,
483
             struct bgp_path_info *bpi)
484
0
{
485
0
  stream_putc(s, BGP_AIGP_TLV_METRIC);
486
0
  stream_putw(s, BGP_AIGP_TLV_METRIC_LEN);
487
0
  stream_putq(s, bgp_aigp_metric_total(bpi));
488
0
}
489
490
static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
491
0
{
492
0
  uint8_t *data = pnt;
493
0
  uint8_t tlv_type;
494
0
  uint16_t tlv_length;
495
0
  uint8_t *end = data + length;
496
497
0
  if (length < 3) {
498
0
    zlog_err("Bad AIGP attribute length (MUST be minimum 3): %u",
499
0
       length);
500
0
    return false;
501
0
  }
502
503
0
  while (length) {
504
0
    size_t data_len = end - data;
505
506
0
    tlv_type = *data;
507
508
0
    if (data_len - 1 < 2)
509
0
      return false;
510
511
0
    ptr_get_be16(data + 1, &tlv_length);
512
0
    (void)data;
513
514
0
    if (length < tlv_length) {
515
0
      zlog_err(
516
0
        "Bad AIGP attribute length: %u, but TLV length: %u",
517
0
        length, tlv_length);
518
0
      return false;
519
0
    }
520
521
0
    if (tlv_length < 3) {
522
0
      zlog_err("Bad AIGP TLV length (MUST be minimum 3): %u",
523
0
         tlv_length);
524
0
      return false;
525
0
    }
526
527
    /* AIGP TLV, Length: 11 */
528
0
    if (tlv_type == BGP_AIGP_TLV_METRIC &&
529
0
        tlv_length != BGP_AIGP_TLV_METRIC_LEN) {
530
0
      zlog_err("Bad AIGP TLV (%s) length: %u",
531
0
         BGP_AIGP_TLV_METRIC_DESC, tlv_length);
532
0
      return false;
533
0
    }
534
535
0
    data += tlv_length;
536
0
    length -= tlv_length;
537
0
  }
538
539
0
  return true;
540
0
}
541
542
static void *srv6_l3vpn_hash_alloc(void *p)
543
6
{
544
6
  return p;
545
6
}
546
547
static void srv6_l3vpn_free(struct bgp_attr_srv6_l3vpn *l3vpn)
548
10
{
549
10
  XFREE(MTYPE_BGP_SRV6_L3VPN, l3vpn);
550
10
}
551
552
static struct bgp_attr_srv6_l3vpn *
553
srv6_l3vpn_intern(struct bgp_attr_srv6_l3vpn *l3vpn)
554
6
{
555
6
  struct bgp_attr_srv6_l3vpn *find;
556
557
6
  find = hash_get(srv6_l3vpn_hash, l3vpn, srv6_l3vpn_hash_alloc);
558
6
  if (find != l3vpn)
559
0
    srv6_l3vpn_free(l3vpn);
560
6
  find->refcnt++;
561
6
  return find;
562
6
}
563
564
static void srv6_l3vpn_unintern(struct bgp_attr_srv6_l3vpn **l3vpnp)
565
10
{
566
10
  struct bgp_attr_srv6_l3vpn *l3vpn = *l3vpnp;
567
568
10
  if (l3vpn->refcnt)
569
6
    l3vpn->refcnt--;
570
571
10
  if (l3vpn->refcnt == 0) {
572
10
    hash_release(srv6_l3vpn_hash, l3vpn);
573
10
    srv6_l3vpn_free(l3vpn);
574
10
    *l3vpnp = NULL;
575
10
  }
576
10
}
577
578
static void *srv6_vpn_hash_alloc(void *p)
579
0
{
580
0
  return p;
581
0
}
582
583
static void srv6_vpn_free(struct bgp_attr_srv6_vpn *vpn)
584
0
{
585
0
  XFREE(MTYPE_BGP_SRV6_VPN, vpn);
586
0
}
587
588
static struct bgp_attr_srv6_vpn *srv6_vpn_intern(struct bgp_attr_srv6_vpn *vpn)
589
0
{
590
0
  struct bgp_attr_srv6_vpn *find;
591
592
0
  find = hash_get(srv6_vpn_hash, vpn, srv6_vpn_hash_alloc);
593
0
  if (find != vpn)
594
0
    srv6_vpn_free(vpn);
595
0
  find->refcnt++;
596
0
  return find;
597
0
}
598
599
static void srv6_vpn_unintern(struct bgp_attr_srv6_vpn **vpnp)
600
0
{
601
0
  struct bgp_attr_srv6_vpn *vpn = *vpnp;
602
603
0
  if (vpn->refcnt)
604
0
    vpn->refcnt--;
605
606
0
  if (vpn->refcnt == 0) {
607
0
    hash_release(srv6_vpn_hash, vpn);
608
0
    srv6_vpn_free(vpn);
609
0
    *vpnp = NULL;
610
0
  }
611
0
}
612
613
static uint32_t srv6_l3vpn_hash_key_make(const void *p)
614
16
{
615
16
  const struct bgp_attr_srv6_l3vpn *l3vpn = p;
616
16
  uint32_t key = 0;
617
618
16
  key = jhash(&l3vpn->sid, 16, key);
619
16
  key = jhash_1word(l3vpn->sid_flags, key);
620
16
  key = jhash_1word(l3vpn->endpoint_behavior, key);
621
16
  key = jhash_1word(l3vpn->loc_block_len, key);
622
16
  key = jhash_1word(l3vpn->loc_node_len, key);
623
16
  key = jhash_1word(l3vpn->func_len, key);
624
16
  key = jhash_1word(l3vpn->arg_len, key);
625
16
  key = jhash_1word(l3vpn->transposition_len, key);
626
16
  key = jhash_1word(l3vpn->transposition_offset, key);
627
16
  return key;
628
16
}
629
630
static bool srv6_l3vpn_hash_cmp(const void *p1, const void *p2)
631
6
{
632
6
  const struct bgp_attr_srv6_l3vpn *l3vpn1 = p1;
633
6
  const struct bgp_attr_srv6_l3vpn *l3vpn2 = p2;
634
635
6
  return sid_same(&l3vpn1->sid, &l3vpn2->sid)
636
6
         && l3vpn1->sid_flags == l3vpn2->sid_flags
637
6
         && l3vpn1->endpoint_behavior == l3vpn2->endpoint_behavior
638
6
         && l3vpn1->loc_block_len == l3vpn2->loc_block_len
639
6
         && l3vpn1->loc_node_len == l3vpn2->loc_node_len
640
6
         && l3vpn1->func_len == l3vpn2->func_len
641
6
         && l3vpn1->arg_len == l3vpn2->arg_len
642
6
         && l3vpn1->transposition_len == l3vpn2->transposition_len
643
6
         && l3vpn1->transposition_offset == l3vpn2->transposition_offset;
644
6
}
645
646
static bool srv6_l3vpn_same(const struct bgp_attr_srv6_l3vpn *h1,
647
          const struct bgp_attr_srv6_l3vpn *h2)
648
0
{
649
0
  if (h1 == h2)
650
0
    return true;
651
0
  else if (h1 == NULL || h2 == NULL)
652
0
    return false;
653
0
  else
654
0
    return srv6_l3vpn_hash_cmp((const void *)h1, (const void *)h2);
655
0
}
656
657
static unsigned int srv6_vpn_hash_key_make(const void *p)
658
0
{
659
0
  const struct bgp_attr_srv6_vpn *vpn = p;
660
0
  uint32_t key = 0;
661
662
0
  key = jhash(&vpn->sid, 16, key);
663
0
  key = jhash_1word(vpn->sid_flags, key);
664
0
  return key;
665
0
}
666
667
static bool srv6_vpn_hash_cmp(const void *p1, const void *p2)
668
0
{
669
0
  const struct bgp_attr_srv6_vpn *vpn1 = p1;
670
0
  const struct bgp_attr_srv6_vpn *vpn2 = p2;
671
672
0
  return sid_same(&vpn1->sid, &vpn2->sid)
673
0
         && vpn1->sid_flags == vpn2->sid_flags;
674
0
}
675
676
static bool srv6_vpn_same(const struct bgp_attr_srv6_vpn *h1,
677
        const struct bgp_attr_srv6_vpn *h2)
678
0
{
679
0
  if (h1 == h2)
680
0
    return true;
681
0
  else if (h1 == NULL || h2 == NULL)
682
0
    return false;
683
0
  else
684
0
    return srv6_vpn_hash_cmp((const void *)h1, (const void *)h2);
685
0
}
686
687
static void srv6_init(void)
688
1
{
689
1
  srv6_l3vpn_hash =
690
1
    hash_create(srv6_l3vpn_hash_key_make, srv6_l3vpn_hash_cmp,
691
1
          "BGP Prefix-SID SRv6-L3VPN-Service-TLV");
692
1
  srv6_vpn_hash = hash_create(srv6_vpn_hash_key_make, srv6_vpn_hash_cmp,
693
1
            "BGP Prefix-SID SRv6-VPN-Service-TLV");
694
1
}
695
696
static void srv6_finish(void)
697
0
{
698
0
  hash_clean_and_free(&srv6_l3vpn_hash,
699
0
          (void (*)(void *))srv6_l3vpn_free);
700
0
  hash_clean_and_free(&srv6_vpn_hash, (void (*)(void *))srv6_vpn_free);
701
0
}
702
703
static unsigned int transit_hash_key_make(const void *p)
704
100
{
705
100
  const struct transit *transit = p;
706
707
100
  return jhash(transit->val, transit->length, 0);
708
100
}
709
710
static bool transit_hash_cmp(const void *p1, const void *p2)
711
50
{
712
50
  const struct transit *transit1 = p1;
713
50
  const struct transit *transit2 = p2;
714
715
50
  return (transit1->length == transit2->length
716
50
    && memcmp(transit1->val, transit2->val, transit1->length) == 0);
717
50
}
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
409
{
1188
409
  struct ecommunity *ecomm = NULL;
1189
409
  struct ecommunity *ipv6_ecomm = NULL;
1190
409
  struct cluster_list *cluster;
1191
409
  struct lcommunity *lcomm = NULL;
1192
409
  struct community *comm = NULL;
1193
1194
  /* aspath refcount shoud be decrement. */
1195
409
  aspath_unintern(&attr->aspath);
1196
409
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
1197
1198
409
  comm = bgp_attr_get_community(attr);
1199
409
  community_unintern(&comm);
1200
409
  bgp_attr_set_community(attr, NULL);
1201
1202
409
  ecomm = bgp_attr_get_ecommunity(attr);
1203
409
  ecommunity_unintern(&ecomm);
1204
409
  bgp_attr_set_ecommunity(attr, NULL);
1205
1206
409
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1207
409
  ecommunity_unintern(&ipv6_ecomm);
1208
409
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1209
1210
409
  lcomm = bgp_attr_get_lcommunity(attr);
1211
409
  lcommunity_unintern(&lcomm);
1212
409
  bgp_attr_set_lcommunity(attr, NULL);
1213
1214
409
  cluster = bgp_attr_get_cluster(attr);
1215
409
  if (cluster) {
1216
19
    cluster_unintern(&cluster);
1217
19
    bgp_attr_set_cluster(attr, cluster);
1218
19
  }
1219
409
  UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
1220
1221
409
  struct transit *transit = bgp_attr_get_transit(attr);
1222
1223
409
  if (transit) {
1224
50
    transit_unintern(&transit);
1225
50
    bgp_attr_set_transit(attr, transit);
1226
50
  }
1227
1228
409
  if (attr->encap_subtlvs)
1229
7
    encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
1230
1231
409
#ifdef ENABLE_BGP_VNC
1232
409
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1233
409
    bgp_attr_get_vnc_subtlvs(attr);
1234
1235
409
  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
409
#endif
1240
1241
409
  if (attr->srv6_l3vpn)
1242
10
    srv6_l3vpn_unintern(&attr->srv6_l3vpn);
1243
1244
409
  if (attr->srv6_vpn)
1245
0
    srv6_vpn_unintern(&attr->srv6_vpn);
1246
409
}
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.17k
{
1273
2.17k
  struct ecommunity *ecomm;
1274
2.17k
  struct ecommunity *ipv6_ecomm;
1275
2.17k
  struct cluster_list *cluster;
1276
2.17k
  struct lcommunity *lcomm;
1277
2.17k
  struct community *comm;
1278
1279
2.17k
  if (attr->aspath && !attr->aspath->refcnt) {
1280
0
    aspath_free(attr->aspath);
1281
0
    attr->aspath = NULL;
1282
0
  }
1283
2.17k
  comm = bgp_attr_get_community(attr);
1284
2.17k
  if (comm && !comm->refcnt)
1285
478
    community_free(&comm);
1286
2.17k
  bgp_attr_set_community(attr, NULL);
1287
1288
2.17k
  ecomm = bgp_attr_get_ecommunity(attr);
1289
2.17k
  if (ecomm && !ecomm->refcnt)
1290
0
    ecommunity_free(&ecomm);
1291
2.17k
  bgp_attr_set_ecommunity(attr, NULL);
1292
1293
2.17k
  ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
1294
2.17k
  if (ipv6_ecomm && !ipv6_ecomm->refcnt)
1295
0
    ecommunity_free(&ipv6_ecomm);
1296
2.17k
  bgp_attr_set_ipv6_ecommunity(attr, NULL);
1297
1298
2.17k
  lcomm = bgp_attr_get_lcommunity(attr);
1299
2.17k
  if (lcomm && !lcomm->refcnt)
1300
0
    lcommunity_free(&lcomm);
1301
2.17k
  bgp_attr_set_lcommunity(attr, NULL);
1302
1303
2.17k
  cluster = bgp_attr_get_cluster(attr);
1304
2.17k
  if (cluster && !cluster->refcnt) {
1305
0
    cluster_free(cluster);
1306
0
    bgp_attr_set_cluster(attr, NULL);
1307
0
  }
1308
1309
2.17k
  struct transit *transit = bgp_attr_get_transit(attr);
1310
1311
2.17k
  if (transit && !transit->refcnt) {
1312
0
    transit_free(transit);
1313
0
    bgp_attr_set_transit(attr, NULL);
1314
0
  }
1315
2.17k
  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.17k
  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.17k
  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.17k
#ifdef ENABLE_BGP_VNC
1328
2.17k
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
1329
2.17k
    bgp_attr_get_vnc_subtlvs(attr);
1330
1331
2.17k
  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.17k
#endif
1336
2.17k
}
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
144
{
1347
144
  struct peer *const peer = args->peer;
1348
144
  struct attr *const attr = args->attr;
1349
144
  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
144
  uint8_t *notify_datap = (length > 0 ? args->startp : NULL);
1355
1356
144
  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
144
  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
144
  stream_set_getp(BGP_INPUT(peer),
1375
144
      (args->startp - STREAM_DATA(BGP_INPUT(peer)))
1376
144
        + args->total);
1377
1378
144
  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
3
  case BGP_ATTR_AS4_AGGREGATOR:
1385
3
  case BGP_ATTR_AGGREGATOR:
1386
7
  case BGP_ATTR_ATOMIC_AGGREGATE:
1387
7
    return BGP_ATTR_PARSE_PROCEED;
1388
1389
  /* Core attributes, particularly ones which may influence route
1390
   * selection, should be treat-as-withdraw.
1391
   */
1392
14
  case BGP_ATTR_ORIGIN:
1393
23
  case BGP_ATTR_AS_PATH:
1394
36
  case BGP_ATTR_AS4_PATH:
1395
39
  case BGP_ATTR_NEXT_HOP:
1396
47
  case BGP_ATTR_MULTI_EXIT_DISC:
1397
48
  case BGP_ATTR_LOCAL_PREF:
1398
50
  case BGP_ATTR_COMMUNITIES:
1399
52
  case BGP_ATTR_EXT_COMMUNITIES:
1400
55
  case BGP_ATTR_IPV6_EXT_COMMUNITIES:
1401
58
  case BGP_ATTR_LARGE_COMMUNITIES:
1402
58
  case BGP_ATTR_ORIGINATOR_ID:
1403
59
  case BGP_ATTR_CLUSTER_LIST:
1404
60
  case BGP_ATTR_PMSI_TUNNEL:
1405
67
  case BGP_ATTR_ENCAP:
1406
67
  case BGP_ATTR_OTC:
1407
67
    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
144
  }
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
70
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
1420
42
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1421
37
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
1422
15
    return BGP_ATTR_PARSE_WITHDRAW;
1423
1424
  /* default to reset */
1425
55
  return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
1426
70
}
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
6
{
1438
6
  uint8_t seen = 0, i;
1439
6
  uint8_t real_flags = args->flags;
1440
6
  const uint8_t attr_code = args->type;
1441
1442
6
  desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1443
6
  real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
1444
24
  for (i = 0; i <= 2; i++) /* O,T,P, but not E */
1445
18
    if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1446
18
        != CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
1447
9
      flog_err(EC_BGP_ATTR_FLAG,
1448
9
         "%s attribute must%s be flagged as \"%s\"",
1449
9
         lookup_msg(attr_str, attr_code, NULL),
1450
9
         CHECK_FLAG(desired_flags, attr_flag_str[i].key)
1451
9
           ? ""
1452
9
           : " not",
1453
9
         attr_flag_str[i].str);
1454
9
      seen = 1;
1455
9
    }
1456
6
  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
6
}
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
893
{
1498
893
  uint8_t mask = BGP_ATTR_FLAG_EXTLEN;
1499
893
  const uint8_t flags = args->flags;
1500
893
  const uint8_t attr_code = args->type;
1501
1502
  /* there may be attributes we don't know about */
1503
893
  if (attr_code > attr_flags_values_max)
1504
171
    return false;
1505
722
  if (attr_flags_values[attr_code] == 0)
1506
66
    return false;
1507
1508
  /* RFC4271, "For well-known attributes, the Transitive bit MUST be set
1509
   * to
1510
   * 1."
1511
   */
1512
656
  if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags)
1513
228
      && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) {
1514
25
    flog_err(
1515
25
      EC_BGP_ATTR_FLAG,
1516
25
      "%s well-known attributes must have transitive flag set (%x)",
1517
25
      lookup_msg(attr_str, attr_code, NULL), flags);
1518
25
    return true;
1519
25
  }
1520
1521
  /* "For well-known attributes and for optional non-transitive
1522
   * attributes,
1523
   *  the Partial bit MUST be set to 0."
1524
   */
1525
631
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) {
1526
205
    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
205
    if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1533
205
        && !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
205
  }
1540
1541
  /* Optional transitive attributes may go through speakers that don't
1542
   * reocgnise them and set the Partial bit.
1543
   */
1544
629
  if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
1545
426
      && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
1546
262
    SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
1547
1548
629
  if ((flags & ~mask) == attr_flags_values[attr_code])
1549
623
    return false;
1550
1551
6
  bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
1552
6
  return true;
1553
629
}
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
59
{
1559
59
  struct peer *const peer = args->peer;
1560
59
  struct attr *const attr = args->attr;
1561
59
  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
59
  if (length != 1) {
1569
2
    flog_err(EC_BGP_ATTR_LEN,
1570
2
       "Origin attribute length is not one %d", length);
1571
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1572
2
            args->total);
1573
2
  }
1574
1575
  /* Fetch origin attribute. */
1576
57
  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
57
  if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP)
1582
18
      && (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
56
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
1591
1592
56
  return 0;
1593
57
}
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
76
{
1599
76
  struct attr *const attr = args->attr;
1600
76
  struct peer *const peer = args->peer;
1601
76
  const bgp_size_t length = args->length;
1602
76
  enum asnotation_mode asnotation;
1603
1604
76
  asnotation = bgp_get_asnotation(
1605
76
    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
76
  attr->aspath =
1611
76
    aspath_parse(peer->curr, length,
1612
76
           CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) &&
1613
76
             CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV),
1614
76
           asnotation);
1615
1616
  /* In case of IBGP, length will be zero. */
1617
76
  if (!attr->aspath) {
1618
5
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1619
5
       "Malformed AS path from %s, length is %d", peer->host,
1620
5
       length);
1621
5
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1622
5
            0);
1623
5
  }
1624
1625
  /* Conformant BGP speakers SHOULD NOT send BGP
1626
   * UPDATE messages containing AS_SET or AS_CONFED_SET.  Upon receipt of
1627
   * such messages, conformant BGP speakers SHOULD use the "Treat-as-
1628
   * withdraw" error handling behavior as per [RFC7606].
1629
   */
1630
71
  if (peer->bgp && peer->bgp->reject_as_sets &&
1631
0
      aspath_check_as_sets(attr->aspath)) {
1632
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1633
0
       "AS_SET and AS_CONFED_SET are deprecated from %pBP",
1634
0
       peer);
1635
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1636
0
            0);
1637
0
  }
1638
1639
  /* Set aspath attribute flag. */
1640
71
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
1641
1642
71
  return BGP_ATTR_PARSE_PROCEED;
1643
71
}
1644
1645
static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
1646
                 struct attr *const attr)
1647
56
{
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
56
  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
56
  (void)peer_sort(peer);
1664
1665
  /* Confederation sanity check. */
1666
56
  if ((peer->sort == BGP_PEER_CONFED
1667
0
       && !aspath_left_confed_check(attr->aspath))
1668
56
      || (peer->sort == BGP_PEER_EBGP
1669
56
    && 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
56
  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
56
  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
56
  if (peer->change_local_as
1697
0
      && !CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) {
1698
0
    aspath = aspath_dup(attr->aspath);
1699
0
    aspath = aspath_add_seq(aspath, peer->change_local_as);
1700
0
    aspath_unintern(&attr->aspath);
1701
0
    attr->aspath = aspath_intern(aspath);
1702
0
  }
1703
1704
56
  return BGP_ATTR_PARSE_PROCEED;
1705
56
}
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
36
{
1712
36
  struct peer *const peer = args->peer;
1713
36
  struct attr *const attr = args->attr;
1714
36
  const bgp_size_t length = args->length;
1715
36
  enum asnotation_mode asnotation;
1716
1717
36
  asnotation = bgp_get_asnotation(peer->bgp);
1718
1719
36
  *as4_path = aspath_parse(peer->curr, length, 1, asnotation);
1720
1721
  /* In case of IBGP, length will be zero. */
1722
36
  if (!*as4_path) {
1723
13
    flog_err(EC_BGP_ATTR_MAL_AS_PATH,
1724
13
       "Malformed AS4 path from %s, length is %d", peer->host,
1725
13
       length);
1726
13
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
1727
13
            0);
1728
13
  }
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
23
  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
23
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
1745
1746
23
  return BGP_ATTR_PARSE_PROCEED;
1747
23
}
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
60
{
1779
60
  struct peer *const peer = args->peer;
1780
60
  struct attr *const attr = args->attr;
1781
60
  const bgp_size_t length = args->length;
1782
1783
  /* Check nexthop attribute length. */
1784
60
  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
60
  attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
1793
60
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1794
1795
60
  return BGP_ATTR_PARSE_PROCEED;
1796
60
}
1797
1798
/* MED atrribute. */
1799
static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
1800
2
{
1801
2
  struct peer *const peer = args->peer;
1802
2
  struct attr *const attr = args->attr;
1803
2
  const bgp_size_t length = args->length;
1804
1805
  /* Length check. */
1806
2
  if (length != 4) {
1807
2
    flog_err(EC_BGP_ATTR_LEN,
1808
2
       "MED attribute length isn't four [%d]", length);
1809
1810
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1811
2
            args->total);
1812
2
  }
1813
1814
0
  attr->med = stream_getl(peer->curr);
1815
1816
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
1817
1818
0
  return BGP_ATTR_PARSE_PROCEED;
1819
2
}
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
2
{
1864
2
  struct peer *const peer = args->peer;
1865
2
  struct attr *const attr = args->attr;
1866
2
  const bgp_size_t length = args->length;
1867
1868
  /* Length check. */
1869
2
  if (length != 0) {
1870
2
    flog_err(EC_BGP_ATTR_LEN,
1871
2
       "ATOMIC_AGGREGATE attribute length isn't 0 [%u]",
1872
2
       length);
1873
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1874
2
            args->total);
1875
2
  }
1876
1877
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1878
0
    goto atomic_ignore;
1879
1880
  /* Set atomic aggregate flag. */
1881
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
1882
1883
0
  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
0
}
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
2
{
1956
2
  struct peer *const peer = args->peer;
1957
2
  struct attr *const attr = args->attr;
1958
2
  const bgp_size_t length = args->length;
1959
2
  as_t aggregator_as;
1960
1961
2
  if (length != 8) {
1962
2
    flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]",
1963
2
       length);
1964
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
1965
2
            0);
1966
2
  }
1967
1968
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
1969
0
    goto as4_aggregator_ignore;
1970
1971
0
  aggregator_as = stream_getl(peer->curr);
1972
1973
0
  *as4_aggregator_as = aggregator_as;
1974
0
  as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr);
1975
1976
  /* Codification of AS 0 Processing */
1977
0
  if (aggregator_as == BGP_AS_ZERO) {
1978
0
    flog_err(EC_BGP_ATTR_LEN,
1979
0
       "%s: AS4_AGGREGATOR AS number is 0 for aspath: %s",
1980
0
       peer->host, aspath_print(attr->aspath));
1981
1982
0
    if (bgp_debug_update(peer, NULL, NULL, 1)) {
1983
0
      char attr_str[BUFSIZ] = {0};
1984
1985
0
      bgp_dump_attr(attr, attr_str, sizeof(attr_str));
1986
1987
0
      zlog_debug("%s: attributes: %s", __func__, attr_str);
1988
0
    }
1989
0
  } else {
1990
0
    attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
1991
0
  }
1992
1993
0
  return BGP_ATTR_PARSE_PROCEED;
1994
1995
0
as4_aggregator_ignore:
1996
0
  stream_forward_getp(peer->curr, length);
1997
1998
0
  return bgp_attr_ignore(peer, args->type);
1999
0
}
2000
2001
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
2002
 */
2003
static enum bgp_attr_parse_ret
2004
bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
2005
       struct aspath *as4_path, as_t as4_aggregator,
2006
       struct in_addr *as4_aggregator_addr)
2007
56
{
2008
56
  int ignore_as4_path = 0;
2009
56
  struct aspath *newpath;
2010
2011
56
  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
56
  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
56
    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
56
    return BGP_ATTR_PARSE_PROCEED;
2041
56
  }
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
30
{
2108
30
  struct peer *const peer = args->peer;
2109
30
  struct attr *const attr = args->attr;
2110
30
  const bgp_size_t length = args->length;
2111
2112
30
  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
30
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2119
0
    goto community_ignore;
2120
2121
30
  bgp_attr_set_community(
2122
30
    attr,
2123
30
    community_parse((uint32_t *)stream_pnt(peer->curr), length));
2124
2125
  /* XXX: fix community_parse to use stream API and remove this */
2126
30
  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
30
  if (!bgp_attr_get_community(attr))
2132
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2133
0
            args->total);
2134
2135
30
  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
30
}
2142
2143
/* Originator ID attribute. */
2144
static enum bgp_attr_parse_ret
2145
bgp_attr_originator_id(struct bgp_attr_parser_args *args)
2146
8
{
2147
8
  struct peer *const peer = args->peer;
2148
8
  struct attr *const attr = args->attr;
2149
8
  const bgp_size_t length = args->length;
2150
2151
  /* if received from an internal neighbor, it SHALL be considered
2152
   * malformed if its length is not equal to 4. If malformed, the
2153
   * UPDATE message SHALL be handled using the approach of "treat-as-
2154
   * withdraw".
2155
   */
2156
8
  if (length != 4) {
2157
0
    flog_err(EC_BGP_ATTR_LEN, "Bad originator ID length %d",
2158
0
       length);
2159
2160
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2161
0
            args->total);
2162
0
  }
2163
2164
8
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2165
0
    goto originator_id_ignore;
2166
2167
8
  attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
2168
2169
8
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
2170
2171
8
  return BGP_ATTR_PARSE_PROCEED;
2172
2173
0
originator_id_ignore:
2174
0
  stream_forward_getp(peer->curr, length);
2175
2176
0
  return bgp_attr_ignore(peer, args->type);
2177
8
}
2178
2179
/* Cluster list attribute. */
2180
static enum bgp_attr_parse_ret
2181
bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
2182
19
{
2183
19
  struct peer *const peer = args->peer;
2184
19
  struct attr *const attr = args->attr;
2185
19
  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
19
  if (length == 0 || length % 4) {
2193
0
    flog_err(EC_BGP_ATTR_LEN, "Bad cluster list length %d", length);
2194
2195
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2196
0
            args->total);
2197
0
  }
2198
2199
19
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2200
0
    goto cluster_list_ignore;
2201
2202
19
  bgp_attr_set_cluster(
2203
19
    attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
2204
19
            length));
2205
2206
  /* XXX: Fix cluster_parse to use stream API and then remove this */
2207
19
  stream_forward_getp(peer->curr, length);
2208
2209
19
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
2210
2211
19
  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
19
}
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
121
{
2223
121
  iana_afi_t pkt_afi;
2224
121
  afi_t afi;
2225
121
  iana_safi_t pkt_safi;
2226
121
  safi_t safi;
2227
121
  bgp_size_t nlri_len;
2228
121
  size_t start;
2229
121
  struct stream *s;
2230
121
  struct peer *const peer = args->peer;
2231
121
  struct attr *const attr = args->attr;
2232
121
  const bgp_size_t length = args->length;
2233
2234
  /* Set end of packet. */
2235
121
  s = BGP_INPUT(peer);
2236
121
  start = stream_get_getp(s);
2237
2238
/* safe to read statically sized header? */
2239
121
#define BGP_MP_REACH_MIN_SIZE 5
2240
361
#define LEN_LEFT  (length - (stream_get_getp(s) - start))
2241
121
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) {
2242
0
    zlog_info("%s: %s sent invalid length, %lu, of MP_REACH_NLRI",
2243
0
        __func__, peer->host, (unsigned long)length);
2244
0
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2245
0
  }
2246
2247
  /* Load AFI, SAFI. */
2248
121
  pkt_afi = stream_getw(s);
2249
121
  pkt_safi = stream_getc(s);
2250
2251
  /* Convert AFI, SAFI to internal values, check. */
2252
121
  if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
2253
    /* Log if AFI or SAFI is unrecognized. This is not an error
2254
     * unless
2255
     * the attribute is otherwise malformed.
2256
     */
2257
0
    if (bgp_debug_update(peer, NULL, NULL, 0))
2258
0
      zlog_debug(
2259
0
        "%s sent unrecognizable AFI, %s or, SAFI, %s, of MP_REACH_NLRI",
2260
0
        peer->host, iana_afi2str(pkt_afi),
2261
0
        iana_safi2str(pkt_safi));
2262
0
    return BGP_ATTR_PARSE_ERROR;
2263
0
  }
2264
2265
  /* Get nexthop length. */
2266
121
  attr->mp_nexthop_len = stream_getc(s);
2267
2268
121
  if (LEN_LEFT < attr->mp_nexthop_len) {
2269
0
    zlog_info(
2270
0
      "%s: %s sent next-hop length, %u, in MP_REACH_NLRI which goes past the end of attribute",
2271
0
      __func__, peer->host, attr->mp_nexthop_len);
2272
0
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2273
0
  }
2274
2275
  /* Nexthop length check. */
2276
121
  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
59
  case BGP_ATTR_NHLEN_IPV4:
2296
59
    stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN);
2297
    /* Probably needed for RFC 2283 */
2298
59
    if (attr->nexthop.s_addr == INADDR_ANY)
2299
54
      memcpy(&attr->nexthop.s_addr,
2300
54
             &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN);
2301
59
    break;
2302
61
  case BGP_ATTR_NHLEN_IPV6_GLOBAL:
2303
61
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
2304
61
    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
61
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2309
61
    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
61
    break;
2318
61
  case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
2319
0
  case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
2320
0
    if (attr->mp_nexthop_len
2321
0
        == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2322
0
      stream_getl(s); /* RD high */
2323
0
      stream_getl(s); /* RD low */
2324
0
    }
2325
0
    stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
2326
0
    if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
2327
0
      if (!peer->nexthop.ifp) {
2328
0
        zlog_warn("%s sent a v6 global and LL attribute but global address is a V6 LL and there's no peer interface information. Hence, withdrawing",
2329
0
            peer->host);
2330
0
        return BGP_ATTR_PARSE_WITHDRAW;
2331
0
      }
2332
0
      attr->nh_ifindex = peer->nexthop.ifp->ifindex;
2333
0
    }
2334
0
    if (attr->mp_nexthop_len
2335
0
        == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
2336
0
      stream_getl(s); /* RD high */
2337
0
      stream_getl(s); /* RD low */
2338
0
    }
2339
0
    stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
2340
0
    if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
2341
0
      if (bgp_debug_update(peer, NULL, NULL, 1))
2342
0
        zlog_debug(
2343
0
          "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
2344
0
          peer->host, &attr->mp_nexthop_global,
2345
0
          &attr->mp_nexthop_local);
2346
2347
0
      attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
2348
0
    }
2349
0
    if (!peer->nexthop.ifp) {
2350
0
      zlog_warn("%s sent a v6 LL next-hop and there's no peer interface information. Hence, withdrawing",
2351
0
          peer->host);
2352
0
      return BGP_ATTR_PARSE_WITHDRAW;
2353
0
    }
2354
0
    attr->nh_lla_ifindex = peer->nexthop.ifp->ifindex;
2355
0
    break;
2356
1
  default:
2357
1
    zlog_info("%s: %s sent wrong next-hop length, %d, in MP_REACH_NLRI",
2358
1
        __func__, peer->host, attr->mp_nexthop_len);
2359
1
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2360
121
  }
2361
2362
120
  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
120
  {
2369
120
    uint8_t val;
2370
120
    if ((val = stream_getc(s)))
2371
72
      flog_warn(
2372
120
        EC_BGP_DEFUNCT_SNPA_LEN,
2373
120
        "%s sent non-zero value, %u, for defunct SNPA-length field",
2374
120
        peer->host, val);
2375
120
  }
2376
2377
  /* must have nrli_len, what is left of the attribute */
2378
120
  nlri_len = LEN_LEFT;
2379
120
  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
120
  if (!nlri_len) {
2386
49
    zlog_info("%s: %s sent a zero-length NLRI. Hence, treating as a EOR marker",
2387
49
        __func__, peer->host);
2388
2389
49
    mp_update->afi = afi;
2390
49
    mp_update->safi = safi;
2391
49
    return BGP_ATTR_PARSE_EOR;
2392
49
  }
2393
2394
71
  mp_update->afi = afi;
2395
71
  mp_update->safi = safi;
2396
71
  mp_update->nlri = stream_pnt(s);
2397
71
  mp_update->length = nlri_len;
2398
2399
71
  stream_forward_getp(s, nlri_len);
2400
2401
71
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
2402
2403
71
  return BGP_ATTR_PARSE_PROCEED;
2404
120
#undef LEN_LEFT
2405
120
}
2406
2407
/* Multiprotocol unreachable parse */
2408
int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
2409
       struct bgp_nlri *mp_withdraw)
2410
12
{
2411
12
  struct stream *s;
2412
12
  iana_afi_t pkt_afi;
2413
12
  afi_t afi;
2414
12
  iana_safi_t pkt_safi;
2415
12
  safi_t safi;
2416
12
  uint16_t withdraw_len;
2417
12
  struct peer *const peer = args->peer;
2418
12
  struct attr *const attr = args->attr;
2419
12
  const bgp_size_t length = args->length;
2420
2421
12
  s = peer->curr;
2422
2423
19
#define BGP_MP_UNREACH_MIN_SIZE 3
2424
12
  if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
2425
2
    return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
2426
2427
10
  pkt_afi = stream_getw(s);
2428
10
  pkt_safi = stream_getc(s);
2429
2430
  /* Convert AFI, SAFI to internal values, check. */
2431
10
  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
3
    if (bgp_debug_update(peer, NULL, NULL, 0))
2437
0
      zlog_debug(
2438
3
        "%s: MP_UNREACH received AFI %s or SAFI %s is unrecognized",
2439
3
        peer->host, iana_afi2str(pkt_afi),
2440
3
        iana_safi2str(pkt_safi));
2441
3
    return BGP_ATTR_PARSE_ERROR;
2442
3
  }
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
10
}
2457
2458
/* Large Community attribute. */
2459
static enum bgp_attr_parse_ret
2460
bgp_attr_large_community(struct bgp_attr_parser_args *args)
2461
14
{
2462
14
  struct peer *const peer = args->peer;
2463
14
  struct attr *const attr = args->attr;
2464
14
  const bgp_size_t length = args->length;
2465
2466
  /*
2467
   * Large community follows new attribute format.
2468
   */
2469
14
  if (length == 0) {
2470
1
    bgp_attr_set_lcommunity(attr, NULL);
2471
    /* Empty extcomm doesn't seem to be invalid per se */
2472
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2473
1
            args->total);
2474
1
  }
2475
2476
13
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2477
0
    goto large_community_ignore;
2478
2479
13
  bgp_attr_set_lcommunity(
2480
13
    attr, lcommunity_parse(stream_pnt(peer->curr), length));
2481
  /* XXX: fix ecommunity_parse to use stream API */
2482
13
  stream_forward_getp(peer->curr, length);
2483
2484
13
  if (!bgp_attr_get_lcommunity(attr))
2485
2
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2486
2
            args->total);
2487
2488
11
  return BGP_ATTR_PARSE_PROCEED;
2489
2490
0
large_community_ignore:
2491
0
  stream_forward_getp(peer->curr, length);
2492
2493
0
  return bgp_attr_ignore(peer, args->type);
2494
13
}
2495
2496
/* Extended Community attribute. */
2497
static enum bgp_attr_parse_ret
2498
bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
2499
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
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2527
1
            args->total);
2528
2529
  /* Extract DF election preference and  mobility sequence number */
2530
108
  attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
2531
2532
  /* Extract MAC mobility sequence number, if any. */
2533
108
  attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
2534
108
  attr->sticky = sticky;
2535
2536
  /* Check if this is a Gateway MAC-IP advertisement */
2537
108
  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
108
  if (attr->default_gw)
2544
8
    attr->router_flag = 1;
2545
2546
  /* Check EVPN Neighbor advertisement flags, R-bit */
2547
108
  bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy);
2548
108
  if (proxy)
2549
7
    attr->es_flags |= ATTR_ES_PROXY_ADVERT;
2550
2551
  /* Extract the Rmac, if any */
2552
108
  if (bgp_attr_rmac(attr, &attr->rmac)) {
2553
2
    if (bgp_debug_update(peer, NULL, NULL, 1)
2554
0
        && bgp_mac_exist(&attr->rmac))
2555
0
      zlog_debug("%s: router mac %pEA is self mac", __func__,
2556
2
           &attr->rmac);
2557
2
  }
2558
2559
  /* Get the tunnel type from encap extended community */
2560
108
  bgp_attr_extcom_tunnel_type(attr,
2561
108
    (bgp_encap_types *)&attr->encap_tunneltype);
2562
2563
  /* Extract link bandwidth, if any. */
2564
108
  (void)ecommunity_linkbw_present(bgp_attr_get_ecommunity(attr),
2565
108
          &attr->link_bw);
2566
2567
108
  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
28
{
2574
28
  struct peer *const peer = args->peer;
2575
28
  struct attr *const attr = args->attr;
2576
28
  const bgp_size_t length = args->length;
2577
28
  struct ecommunity *ipv6_ecomm = NULL;
2578
2579
28
  if (length == 0) {
2580
0
    bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2581
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2582
0
            args->total);
2583
0
  }
2584
2585
28
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
2586
0
    goto ipv6_ext_community_ignore;
2587
2588
28
  ipv6_ecomm = ecommunity_parse_ipv6(
2589
28
    stream_pnt(peer->curr), length,
2590
28
    CHECK_FLAG(peer->flags,
2591
28
         PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2592
28
  bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
2593
2594
  /* XXX: fix ecommunity_parse to use stream API */
2595
28
  stream_forward_getp(peer->curr, length);
2596
2597
28
  if (!ipv6_ecomm)
2598
3
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2599
3
            args->total);
2600
2601
25
  return BGP_ATTR_PARSE_PROCEED;
2602
2603
0
ipv6_ext_community_ignore:
2604
0
  stream_forward_getp(peer->curr, length);
2605
2606
0
  return bgp_attr_ignore(peer, args->type);
2607
28
}
2608
2609
/* Parse Tunnel Encap attribute in an UPDATE */
2610
static int bgp_attr_encap(struct bgp_attr_parser_args *args)
2611
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
0
    zlog_err("Tunnel Encap attribute flag isn't optional and transitive %d",
2622
0
       flag);
2623
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2624
0
            args->total);
2625
0
  }
2626
2627
8
  if (BGP_ATTR_ENCAP == type) {
2628
    /* read outer TLV type and length */
2629
8
    uint16_t tlv_length;
2630
2631
8
    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
8
    tunneltype = stream_getw(BGP_INPUT(peer));
2639
8
    tlv_length = stream_getw(BGP_INPUT(peer));
2640
8
    length -= 4;
2641
2642
8
    if (tlv_length != length) {
2643
8
      zlog_info("%s: tlv_length(%d) != length(%d)",
2644
8
          __func__, tlv_length, length);
2645
8
    }
2646
8
  }
2647
2648
561
  while (length >= 4) {
2649
560
    uint16_t subtype = 0;
2650
560
    uint16_t sublength = 0;
2651
560
    struct bgp_attr_encap_subtlv *tlv;
2652
2653
560
    if (BGP_ATTR_ENCAP == type) {
2654
560
      subtype = stream_getc(BGP_INPUT(peer));
2655
560
      sublength = stream_getc(BGP_INPUT(peer));
2656
560
      length -= 2;
2657
560
#ifdef ENABLE_BGP_VNC
2658
560
    } 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
560
    if (sublength > length) {
2666
7
      zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d",
2667
7
         sublength, length);
2668
7
      return bgp_attr_malformed(args,
2669
7
              BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2670
7
              args->total);
2671
7
    }
2672
2673
    /* alloc and copy sub-tlv */
2674
    /* TBD make sure these are freed when attributes are released */
2675
553
    tlv = XCALLOC(MTYPE_ENCAP_TLV,
2676
553
            sizeof(struct bgp_attr_encap_subtlv) + sublength);
2677
553
    tlv->type = subtype;
2678
553
    tlv->length = sublength;
2679
553
    stream_get(tlv->value, peer->curr, sublength);
2680
553
    length -= sublength;
2681
2682
    /* attach tlv to encap chain */
2683
553
    if (BGP_ATTR_ENCAP == type) {
2684
553
      struct bgp_attr_encap_subtlv *stlv_last;
2685
553
      for (stlv_last = attr->encap_subtlvs;
2686
32.9k
           stlv_last && stlv_last->next;
2687
32.3k
           stlv_last = stlv_last->next)
2688
32.3k
        ;
2689
553
      if (stlv_last) {
2690
545
        stlv_last->next = tlv;
2691
545
      } else {
2692
8
        attr->encap_subtlvs = tlv;
2693
8
      }
2694
553
#ifdef ENABLE_BGP_VNC
2695
553
    } 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
553
  }
2711
2712
1
  if (BGP_ATTR_ENCAP == type) {
2713
1
    attr->encap_tunneltype = tunneltype;
2714
1
  }
2715
2716
1
  if (length) {
2717
    /* spurious leftover data */
2718
0
    zlog_err("Tunnel Encap attribute length is bad: %d leftover octets",
2719
0
       length);
2720
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2721
0
            args->total);
2722
0
  }
2723
2724
1
  return 0;
2725
1
}
2726
2727
2728
/* SRv6 Service Data Sub-Sub-TLV attribute
2729
 * draft-ietf-bess-srv6-services-07
2730
 */
2731
static enum bgp_attr_parse_ret
2732
bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
2733
9
{
2734
9
  struct peer *const peer = args->peer;
2735
9
  struct attr *const attr = args->attr;
2736
9
  uint8_t type, loc_block_len, loc_node_len, func_len, arg_len,
2737
9
    transposition_len, transposition_offset;
2738
9
  uint16_t length;
2739
9
  size_t headersz = sizeof(type) + sizeof(length);
2740
2741
9
  if (STREAM_READABLE(peer->curr) < headersz) {
2742
0
    flog_err(
2743
0
      EC_BGP_ATTR_LEN,
2744
0
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %zu for attribute header, have %zu remaining in UPDATE)",
2745
0
      headersz, STREAM_READABLE(peer->curr));
2746
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2747
0
            args->total);
2748
0
  }
2749
2750
9
  type = stream_getc(peer->curr);
2751
9
  length = stream_getw(peer->curr);
2752
2753
9
  if (STREAM_READABLE(peer->curr) < length) {
2754
0
    flog_err(
2755
0
      EC_BGP_ATTR_LEN,
2756
0
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2757
0
      length, STREAM_READABLE(peer->curr));
2758
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2759
0
            args->total);
2760
0
  }
2761
2762
9
  if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2763
4
    flog_err(
2764
4
      EC_BGP_ATTR_LEN,
2765
4
      "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
2766
4
      BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2767
4
      length);
2768
4
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2769
4
            args->total);
2770
4
  }
2771
2772
5
  if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
2773
2
    if (STREAM_READABLE(peer->curr) <
2774
2
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
2775
0
      flog_err(
2776
0
        EC_BGP_ATTR_LEN,
2777
0
        "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
2778
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
2779
0
        STREAM_READABLE(peer->curr));
2780
0
      return bgp_attr_malformed(
2781
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2782
0
        args->total);
2783
0
    }
2784
2785
2
    loc_block_len = stream_getc(peer->curr);
2786
2
    loc_node_len = stream_getc(peer->curr);
2787
2
    func_len = stream_getc(peer->curr);
2788
2
    arg_len = stream_getc(peer->curr);
2789
2
    transposition_len = stream_getc(peer->curr);
2790
2
    transposition_offset = stream_getc(peer->curr);
2791
2792
    /* Log SRv6 Service Data Sub-Sub-TLV */
2793
2
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
2794
0
      zlog_debug(
2795
0
        "%s: srv6-l3-srv-data loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u, transposition-len=%u, transposition-offset=%u",
2796
0
        __func__, loc_block_len, loc_node_len, func_len,
2797
0
        arg_len, transposition_len,
2798
0
        transposition_offset);
2799
0
    }
2800
2801
2
    attr->srv6_l3vpn->loc_block_len = loc_block_len;
2802
2
    attr->srv6_l3vpn->loc_node_len = loc_node_len;
2803
2
    attr->srv6_l3vpn->func_len = func_len;
2804
2
    attr->srv6_l3vpn->arg_len = arg_len;
2805
2
    attr->srv6_l3vpn->transposition_len = transposition_len;
2806
2
    attr->srv6_l3vpn->transposition_offset = transposition_offset;
2807
2
  }
2808
2809
3
  else {
2810
3
    if (bgp_debug_update(peer, NULL, NULL, 1))
2811
0
      zlog_debug(
2812
3
        "%s attr SRv6 Service Data Sub-Sub-TLV sub-sub-type=%u is not supported, skipped",
2813
3
        peer->host, type);
2814
2815
3
    stream_forward_getp(peer->curr, length);
2816
3
  }
2817
2818
5
  return BGP_ATTR_PARSE_PROCEED;
2819
5
}
2820
2821
/* SRv6 Service Sub-TLV attribute
2822
 * draft-ietf-bess-srv6-services-07
2823
 */
2824
static enum bgp_attr_parse_ret
2825
bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
2826
21
{
2827
21
  struct peer *const peer = args->peer;
2828
21
  struct attr *const attr = args->attr;
2829
21
  struct in6_addr ipv6_sid;
2830
21
  uint8_t type, sid_flags;
2831
21
  uint16_t length, endpoint_behavior;
2832
21
  size_t headersz = sizeof(type) + sizeof(length);
2833
21
  enum bgp_attr_parse_ret err;
2834
2835
21
  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
21
  type = stream_getc(peer->curr);
2845
21
  length = stream_getw(peer->curr);
2846
2847
21
  if (STREAM_READABLE(peer->curr) < length) {
2848
5
    flog_err(
2849
5
      EC_BGP_ATTR_LEN,
2850
5
      "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %hu for attribute data, have %zu remaining in UPDATE)",
2851
5
      length, STREAM_READABLE(peer->curr));
2852
5
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2853
5
            args->total);
2854
5
  }
2855
2856
16
  if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
2857
11
    if (STREAM_READABLE(peer->curr) <
2858
11
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2859
0
      flog_err(
2860
0
        EC_BGP_ATTR_LEN,
2861
0
        "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
2862
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
2863
0
        STREAM_READABLE(peer->curr));
2864
0
      return bgp_attr_malformed(
2865
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2866
0
        args->total);
2867
0
    }
2868
11
    stream_getc(peer->curr);
2869
11
    stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
2870
11
    sid_flags = stream_getc(peer->curr);
2871
11
    endpoint_behavior = stream_getw(peer->curr);
2872
11
    stream_getc(peer->curr);
2873
2874
    /* Log SRv6 Service Sub-TLV */
2875
11
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
2876
0
      zlog_debug(
2877
11
        "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
2878
11
        __func__, &ipv6_sid, sid_flags,
2879
11
        endpoint_behavior);
2880
2881
    /* Configure from Info */
2882
11
    if (attr->srv6_l3vpn) {
2883
1
      flog_err(EC_BGP_ATTRIBUTE_REPEATED,
2884
1
         "Prefix SID SRv6 L3VPN field repeated");
2885
1
      return bgp_attr_malformed(
2886
1
        args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
2887
1
    }
2888
10
    attr->srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
2889
10
             sizeof(struct bgp_attr_srv6_l3vpn));
2890
10
    sid_copy(&attr->srv6_l3vpn->sid, &ipv6_sid);
2891
10
    attr->srv6_l3vpn->sid_flags = sid_flags;
2892
10
    attr->srv6_l3vpn->endpoint_behavior = endpoint_behavior;
2893
10
    attr->srv6_l3vpn->loc_block_len = 0;
2894
10
    attr->srv6_l3vpn->loc_node_len = 0;
2895
10
    attr->srv6_l3vpn->func_len = 0;
2896
10
    attr->srv6_l3vpn->arg_len = 0;
2897
10
    attr->srv6_l3vpn->transposition_len = 0;
2898
10
    attr->srv6_l3vpn->transposition_offset = 0;
2899
2900
    // Sub-Sub-TLV found
2901
10
    if (length > BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
2902
9
      err = bgp_attr_srv6_service_data(args);
2903
2904
9
      if (err != BGP_ATTR_PARSE_PROCEED)
2905
4
        return err;
2906
9
    }
2907
2908
6
    attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn);
2909
6
  }
2910
2911
  /* Placeholder code for unsupported type */
2912
5
  else {
2913
5
    if (bgp_debug_update(peer, NULL, NULL, 1))
2914
0
      zlog_debug(
2915
5
        "%s attr SRv6 Service Sub-TLV sub-type=%u is not supported, skipped",
2916
5
        peer->host, type);
2917
2918
5
    stream_forward_getp(peer->curr, length);
2919
5
  }
2920
2921
11
  return BGP_ATTR_PARSE_PROCEED;
2922
16
}
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
235
{
2932
235
  struct peer *const peer = args->peer;
2933
235
  struct attr *const attr = args->attr;
2934
235
  uint32_t label_index;
2935
235
  struct in6_addr ipv6_sid;
2936
235
  uint32_t srgb_base;
2937
235
  uint32_t srgb_range;
2938
235
  int srgb_count;
2939
235
  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
235
  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
235
  if (type == BGP_PREFIX_SID_LABEL_INDEX) {
2955
3
    if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
2956
2
      flog_err(EC_BGP_ATTR_LEN,
2957
2
         "Prefix SID label index length is %hu instead of %u",
2958
2
         length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
2959
2
      return bgp_attr_malformed(args,
2960
2
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2961
2
              args->total);
2962
2
    }
2963
2964
    /* Ignore flags and reserved */
2965
1
    stream_getc(peer->curr);
2966
1
    stream_getw(peer->curr);
2967
2968
    /* Fetch the label index and see if it is valid. */
2969
1
    label_index = stream_getl(peer->curr);
2970
1
    if (label_index == BGP_INVALID_LABEL_INDEX)
2971
0
      return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2972
0
              args->total);
2973
2974
    /* Store label index; subsequently, we'll check on
2975
     * address-family */
2976
1
    attr->label_index = label_index;
2977
232
  } else if (type == BGP_PREFIX_SID_IPV6) {
2978
1
    if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
2979
1
      flog_err(EC_BGP_ATTR_LEN,
2980
1
         "Prefix SID IPv6 length is %hu instead of %u",
2981
1
         length, BGP_PREFIX_SID_IPV6_LENGTH);
2982
1
      return bgp_attr_malformed(args,
2983
1
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
2984
1
              args->total);
2985
1
    }
2986
2987
    /* Ignore reserved */
2988
0
    stream_getc(peer->curr);
2989
0
    stream_getw(peer->curr);
2990
2991
0
    stream_get(&ipv6_sid, peer->curr, 16);
2992
231
  } else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) {
2993
    /*
2994
     * ietf-idr-bgp-prefix-sid-05:
2995
     *     Length is the total length of the value portion of the
2996
     *     TLV: 2 + multiple of 6.
2997
     *
2998
     * peer->curr stream readp should be at the beginning of the 16
2999
     * bit flag field at this point in the code.
3000
     */
3001
3002
    /*
3003
     * Check that the TLV length field is sane: at least 2 bytes of
3004
     * flag, and at least 1 SRGB (these are 6 bytes each)
3005
     */
3006
4
    if (length < (2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)) {
3007
0
      flog_err(
3008
0
        EC_BGP_ATTR_LEN,
3009
0
        "Prefix SID Originator SRGB length field claims length of %hu bytes, but the minimum for this TLV type is %u",
3010
0
        length,
3011
0
        2 + BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3012
0
      return bgp_attr_malformed(
3013
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3014
0
        args->total);
3015
0
    }
3016
3017
    /*
3018
     * Check that the portion of the TLV containing the sequence of
3019
     * SRGBs corresponds to a multiple of the SRGB size; to get
3020
     * that length, we skip the 16 bit flags field
3021
     */
3022
4
    stream_getw(peer->curr);
3023
4
    length -= 2;
3024
4
    if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) {
3025
2
      flog_err(
3026
2
        EC_BGP_ATTR_LEN,
3027
2
        "Prefix SID Originator SRGB length field claims attribute SRGB sequence section is %hubytes, but it must be a multiple of %u",
3028
2
        length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
3029
2
      return bgp_attr_malformed(
3030
2
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3031
2
        args->total);
3032
2
    }
3033
3034
2
    srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
3035
3036
168
    for (int i = 0; i < srgb_count; i++) {
3037
166
      stream_get(&srgb_base, peer->curr, 3);
3038
166
      stream_get(&srgb_range, peer->curr, 3);
3039
166
    }
3040
227
  } else if (type == BGP_PREFIX_SID_VPN_SID) {
3041
1
    if (length != BGP_PREFIX_SID_VPN_SID_LENGTH) {
3042
1
      flog_err(EC_BGP_ATTR_LEN,
3043
1
         "Prefix SID VPN SID length is %hu instead of %u",
3044
1
         length, BGP_PREFIX_SID_VPN_SID_LENGTH);
3045
1
      return bgp_attr_malformed(args,
3046
1
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3047
1
              args->total);
3048
1
    }
3049
3050
    /* Parse VPN-SID Sub-TLV */
3051
0
    stream_getc(peer->curr);               /* reserved  */
3052
0
    sid_type = stream_getc(peer->curr);    /* sid_type  */
3053
0
    sid_flags = stream_getc(peer->curr);   /* sid_flags */
3054
0
    stream_get(&ipv6_sid, peer->curr,
3055
0
         sizeof(ipv6_sid)); /* sid_value */
3056
3057
    /* Log VPN-SID Sub-TLV */
3058
0
    if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
3059
0
      zlog_debug(
3060
0
        "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
3061
0
        __func__, &ipv6_sid, sid_type, sid_flags);
3062
3063
    /* Configure from Info */
3064
0
    if (attr->srv6_vpn) {
3065
0
      flog_err(EC_BGP_ATTRIBUTE_REPEATED,
3066
0
         "Prefix SID SRv6 VPN field repeated");
3067
0
      return bgp_attr_malformed(
3068
0
        args, BGP_NOTIFY_UPDATE_MAL_ATTR, args->total);
3069
0
    }
3070
0
    attr->srv6_vpn = XCALLOC(MTYPE_BGP_SRV6_VPN,
3071
0
           sizeof(struct bgp_attr_srv6_vpn));
3072
0
    attr->srv6_vpn->sid_flags = sid_flags;
3073
0
    sid_copy(&attr->srv6_vpn->sid, &ipv6_sid);
3074
0
    attr->srv6_vpn = srv6_vpn_intern(attr->srv6_vpn);
3075
226
  } else if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE) {
3076
21
    if (STREAM_READABLE(peer->curr) < 1) {
3077
0
      flog_err(
3078
0
        EC_BGP_ATTR_LEN,
3079
0
        "Prefix SID SRV6 L3 Service not enough data left, it must be at least 1 byte");
3080
0
      return bgp_attr_malformed(
3081
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3082
0
        args->total);
3083
0
    }
3084
    /* ignore reserved */
3085
21
    stream_getc(peer->curr);
3086
3087
21
    return bgp_attr_srv6_service(args);
3088
21
  }
3089
  /* Placeholder code for Unsupported TLV */
3090
205
  else {
3091
205
    if (bgp_debug_update(peer, NULL, NULL, 1))
3092
0
      zlog_debug(
3093
205
        "%s attr Prefix-SID sub-type=%u is not supported, skipped",
3094
205
        peer->host, type);
3095
3096
205
    stream_forward_getp(peer->curr, length);
3097
205
  }
3098
3099
208
  return BGP_ATTR_PARSE_PROCEED;
3100
235
}
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
255
  while (STREAM_READABLE(peer->curr) > 0
3119
255
         && psid_parsed_length < args->length) {
3120
3121
253
    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
252
    type = stream_getc(peer->curr);
3132
252
    length = stream_getw(peer->curr);
3133
3134
252
    if (STREAM_READABLE(peer->curr) < length) {
3135
17
      flog_err(
3136
17
        EC_BGP_ATTR_LEN,
3137
17
        "Malformed Prefix SID attribute - insufficient data (need %hu for attribute body, have %zu remaining in UPDATE)",
3138
17
        length, STREAM_READABLE(peer->curr));
3139
17
      return bgp_attr_malformed(args,
3140
17
              BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3141
17
              args->total);
3142
17
    }
3143
3144
235
    ret = bgp_attr_psid_sub(type, length, args);
3145
3146
235
    if (ret != BGP_ATTR_PARSE_PROCEED)
3147
16
      return ret;
3148
3149
219
    psid_parsed_length += length + headersz;
3150
3151
219
    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
219
  }
3161
3162
2
  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
1
{
3171
1
  struct peer *const peer = args->peer;
3172
1
  struct attr *const attr = args->attr;
3173
1
  const bgp_size_t length = args->length;
3174
1
  uint8_t tnl_type;
3175
1
  int attr_parse_len = 2 + BGP_LABEL_BYTES;
3176
3177
  /* Verify that the receiver is expecting "ingress replication" as we
3178
   * can only support that.
3179
   */
3180
1
  if (length < attr_parse_len) {
3181
0
    flog_err(EC_BGP_ATTR_LEN, "Bad PMSI tunnel attribute length %d",
3182
0
       length);
3183
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3184
0
            args->total);
3185
0
  }
3186
1
  stream_getc(peer->curr); /* Flags */
3187
1
  tnl_type = stream_getc(peer->curr);
3188
1
  if (tnl_type > PMSI_TNLTYPE_MAX) {
3189
1
    flog_err(EC_BGP_ATTR_PMSI_TYPE,
3190
1
       "Invalid PMSI tunnel attribute type %d", tnl_type);
3191
1
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
3192
1
            args->total);
3193
1
  }
3194
0
  if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
3195
0
    if (length != 9) {
3196
0
      flog_err(EC_BGP_ATTR_PMSI_LEN,
3197
0
         "Bad PMSI tunnel attribute length %d for IR",
3198
0
         length);
3199
0
      return bgp_attr_malformed(
3200
0
        args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3201
0
        args->total);
3202
0
    }
3203
0
  }
3204
3205
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
3206
0
  bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
3207
0
  stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
3208
3209
  /* Forward read pointer of input stream. */
3210
0
  stream_forward_getp(peer->curr, length - attr_parse_len);
3211
3212
0
  return BGP_ATTR_PARSE_PROCEED;
3213
0
}
3214
3215
/* AIGP attribute (rfc7311) */
3216
static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
3217
1
{
3218
1
  struct peer *const peer = args->peer;
3219
1
  struct attr *const attr = args->attr;
3220
1
  const bgp_size_t length = args->length;
3221
1
  uint8_t *s = stream_pnt(peer->curr);
3222
1
  uint64_t aigp = 0;
3223
3224
  /* If an AIGP attribute is received on a BGP session for which
3225
   * AIGP_SESSION is disabled, the attribute MUST be treated exactly
3226
   * as if it were an unrecognized non-transitive attribute.
3227
   * That is, it "MUST be quietly ignored and not passed along to
3228
   * other BGP peers".
3229
   * For Internal BGP (IBGP) sessions, and for External BGP (EBGP)
3230
   * sessions between members of the same BGP Confederation,
3231
   * the default value of AIGP_SESSION SHOULD be "enabled".
3232
   */
3233
1
  if (peer->sort == BGP_PEER_EBGP &&
3234
1
      !CHECK_FLAG(peer->flags, PEER_FLAG_AIGP)) {
3235
1
    zlog_warn(
3236
1
      "%pBP received AIGP attribute, but eBGP peer do not support it",
3237
1
      peer);
3238
1
    goto aigp_ignore;
3239
1
  }
3240
3241
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
3242
0
    goto aigp_ignore;
3243
3244
0
  if (!bgp_attr_aigp_valid(s, length))
3245
0
    goto aigp_ignore;
3246
3247
  /* Extract AIGP Metric TLV */
3248
0
  if (bgp_attr_aigp_get_tlv_metric(s, length, &aigp))
3249
0
    bgp_attr_set_aigp_metric(attr, aigp);
3250
3251
1
aigp_ignore:
3252
1
  stream_forward_getp(peer->curr, length);
3253
3254
1
  return bgp_attr_ignore(peer, args->type);
3255
0
}
3256
3257
/* OTC attribute. */
3258
static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
3259
0
{
3260
0
  struct peer *const peer = args->peer;
3261
0
  struct attr *const attr = args->attr;
3262
0
  const bgp_size_t length = args->length;
3263
3264
  /* Length check. */
3265
0
  if (length != 4) {
3266
0
    flog_err(EC_BGP_ATTR_LEN, "OTC attribute length isn't 4 [%u]",
3267
0
       length);
3268
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
3269
0
            args->total);
3270
0
  }
3271
3272
0
  if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
3273
0
    goto otc_ignore;
3274
3275
0
  attr->otc = stream_getl(peer->curr);
3276
0
  if (!attr->otc) {
3277
0
    flog_err(EC_BGP_ATTR_MAL_AS_PATH, "OTC attribute value is 0");
3278
0
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
3279
0
            args->total);
3280
0
  }
3281
3282
0
  attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
3283
3284
0
  return BGP_ATTR_PARSE_PROCEED;
3285
3286
0
otc_ignore:
3287
0
  stream_forward_getp(peer->curr, length);
3288
3289
0
  return bgp_attr_ignore(peer, args->type);
3290
0
}
3291
3292
/* BGP unknown attribute treatment. */
3293
static enum bgp_attr_parse_ret
3294
bgp_attr_unknown(struct bgp_attr_parser_args *args)
3295
229
{
3296
229
  bgp_size_t total = args->total;
3297
229
  struct transit *transit;
3298
229
  struct peer *const peer = args->peer;
3299
229
  struct attr *const attr = args->attr;
3300
229
  uint8_t *const startp = args->startp;
3301
229
  const uint8_t type = args->type;
3302
229
  const uint8_t flag = args->flags;
3303
229
  const bgp_size_t length = args->length;
3304
3305
229
  if (bgp_debug_update(peer, NULL, NULL, 1))
3306
0
    zlog_debug(
3307
229
      "%s Unknown attribute is received (type %d, length %d)",
3308
229
      peer->host, type, length);
3309
3310
  /* Forward read pointer of input stream. */
3311
229
  stream_forward_getp(peer->curr, length);
3312
3313
229
  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
229
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) {
3321
32
    return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR,
3322
32
            args->total);
3323
32
  }
3324
3325
  /* Unrecognized non-transitive optional attributes must be quietly
3326
     ignored and not passed along to other BGP peers. */
3327
197
  if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS))
3328
110
    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
87
  SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
3335
3336
  /* Store transitive attribute to the end of attr->transit. */
3337
87
  transit = bgp_attr_get_transit(attr);
3338
87
  if (!transit)
3339
61
    transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
3340
3341
87
  transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
3342
87
        transit->length + total);
3343
3344
87
  memcpy(transit->val + transit->length, startp, total);
3345
87
  transit->length += total;
3346
87
  bgp_attr_set_transit(attr, transit);
3347
3348
87
  return BGP_ATTR_PARSE_PROCEED;
3349
197
}
3350
3351
/* Well-known attribute check. */
3352
static int bgp_attr_check(struct peer *peer, struct attr *attr)
3353
98
{
3354
98
  uint8_t type = 0;
3355
3356
  /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an
3357
   * empty UPDATE.  */
3358
98
  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
98
  if ((!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
3367
34
       CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI))))
3368
6
    return BGP_ATTR_PARSE_PROCEED;
3369
3370
92
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN)))
3371
36
    type = BGP_ATTR_ORIGIN;
3372
3373
92
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
3374
36
    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
92
  if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3381
91
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)))
3382
27
    type = BGP_ATTR_NEXT_HOP;
3383
3384
92
  if (peer->sort == BGP_PEER_IBGP
3385
0
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))
3386
0
    type = BGP_ATTR_LOCAL_PREF;
3387
3388
  /* If any of the well-known mandatory attributes are not present
3389
   * in an UPDATE message, then "treat-as-withdraw" MUST be used.
3390
   */
3391
92
  if (type) {
3392
36
    flog_warn(EC_BGP_MISSING_ATTRIBUTE,
3393
36
        "%s Missing well-known attribute %s.", peer->host,
3394
36
        lookup_msg(attr_str, type, NULL));
3395
36
    return BGP_ATTR_PARSE_WITHDRAW;
3396
36
  }
3397
56
  return BGP_ATTR_PARSE_PROCEED;
3398
92
}
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
401
{
3407
401
  enum bgp_attr_parse_ret ret;
3408
401
  uint8_t flag = 0;
3409
401
  uint8_t type = 0;
3410
401
  bgp_size_t length;
3411
401
  uint8_t *startp, *endp;
3412
401
  uint8_t *attr_endp;
3413
401
  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
401
  struct aspath *as4_path = NULL;
3418
401
  as_t as4_aggregator = 0;
3419
401
  struct in_addr as4_aggregator_addr = {.s_addr = 0};
3420
401
  struct transit *transit;
3421
3422
  /* Initialize bitmap. */
3423
401
  memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
3424
3425
  /* End pointer of BGP attribute. */
3426
401
  endp = BGP_INPUT_PNT(peer) + size;
3427
3428
  /* Get attributes to the end of attribute length. */
3429
1.10k
  while (BGP_INPUT_PNT(peer) < endp) {
3430
    /* Check remaining length check.*/
3431
1.00k
    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.00k
    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.00k
    flag = 0xF0 & stream_getc(BGP_INPUT(peer));
3452
1.00k
    type = stream_getc(BGP_INPUT(peer));
3453
3454
    /* Check whether Extended-Length applies and is in bounds */
3455
1.00k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
3456
439
        && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
3457
1
      flog_warn(
3458
1
        EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
3459
1
        "%s: Extended length set, but just %lu bytes of attr header",
3460
1
        peer->host,
3461
1
        (unsigned long)(endp
3462
1
            - stream_pnt(BGP_INPUT(peer))));
3463
3464
1
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3465
1
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3466
1
      ret = BGP_ATTR_PARSE_ERROR;
3467
1
      goto done;
3468
1
    }
3469
3470
    /* Check extended attribue length bit. */
3471
1.00k
    if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN))
3472
438
      length = stream_getw(BGP_INPUT(peer));
3473
562
    else
3474
562
      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.00k
    if (CHECK_BITMAP(seen, type)) {
3481
5
      flog_warn(
3482
5
        EC_BGP_ATTRIBUTE_REPEATED,
3483
5
        "%s: error BGP attribute type %d appears twice in a message",
3484
5
        peer->host, type);
3485
3486
5
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3487
5
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3488
5
      ret = BGP_ATTR_PARSE_ERROR;
3489
5
      goto done;
3490
5
    }
3491
3492
    /* Set type to bitmap to check duplicate attribute.  `type' is
3493
       unsigned char so it never overflow bitmap range. */
3494
3495
995
    SET_BITMAP(seen, type);
3496
3497
    /* Overflow check. */
3498
995
    attr_endp = BGP_INPUT_PNT(peer) + length;
3499
3500
995
    if (attr_endp > endp) {
3501
102
      flog_warn(
3502
102
        EC_BGP_ATTRIBUTE_TOO_LARGE,
3503
102
        "%s: BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p",
3504
102
        peer->host, type, length, size, attr_endp,
3505
102
        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
102
      unsigned char ndata[peer->max_packet_size];
3527
102
      memset(ndata, 0x00, sizeof(ndata));
3528
102
      size_t lfl =
3529
102
        CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
3530
      /* Rewind to end of flag field */
3531
102
      stream_rewind_getp(BGP_INPUT(peer), (1 + lfl));
3532
      /* Type */
3533
102
      stream_get(&ndata[0], BGP_INPUT(peer), 1);
3534
      /* Length */
3535
102
      stream_get(&ndata[1], BGP_INPUT(peer), lfl);
3536
      /* Value */
3537
102
      size_t atl = attr_endp - startp;
3538
102
      size_t ndl = MIN(atl, STREAM_READABLE(BGP_INPUT(peer)));
3539
102
      stream_get(&ndata[lfl + 1], BGP_INPUT(peer), ndl);
3540
3541
102
      bgp_notify_send_with_data(
3542
102
        peer, BGP_NOTIFY_UPDATE_ERR,
3543
102
        BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, ndata,
3544
102
        ndl + lfl + 1);
3545
3546
102
      ret = BGP_ATTR_PARSE_ERROR;
3547
102
      goto done;
3548
102
    }
3549
3550
893
    struct bgp_attr_parser_args attr_args = {
3551
893
      .peer = peer,
3552
893
      .length = length,
3553
893
      .attr = attr,
3554
893
      .type = type,
3555
893
      .flags = flag,
3556
893
      .startp = startp,
3557
893
      .total = attr_endp - startp,
3558
893
    };
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
893
    if (bgp_attr_flag_invalid(&attr_args)) {
3567
33
      ret = bgp_attr_malformed(
3568
33
        &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
3569
33
        attr_args.total);
3570
33
      if (ret == BGP_ATTR_PARSE_PROCEED)
3571
3
        continue;
3572
30
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3573
30
      goto done;
3574
33
    }
3575
3576
    /* OK check attribute and store it's value. */
3577
860
    switch (type) {
3578
59
    case BGP_ATTR_ORIGIN:
3579
59
      ret = bgp_attr_origin(&attr_args);
3580
59
      break;
3581
76
    case BGP_ATTR_AS_PATH:
3582
76
      ret = bgp_attr_aspath(&attr_args);
3583
76
      break;
3584
36
    case BGP_ATTR_AS4_PATH:
3585
36
      ret = bgp_attr_as4_path(&attr_args, &as4_path);
3586
36
      break;
3587
60
    case BGP_ATTR_NEXT_HOP:
3588
60
      ret = bgp_attr_nexthop(&attr_args);
3589
60
      break;
3590
2
    case BGP_ATTR_MULTI_EXIT_DISC:
3591
2
      ret = bgp_attr_med(&attr_args);
3592
2
      break;
3593
4
    case BGP_ATTR_LOCAL_PREF:
3594
4
      ret = bgp_attr_local_pref(&attr_args);
3595
4
      break;
3596
2
    case BGP_ATTR_ATOMIC_AGGREGATE:
3597
2
      ret = bgp_attr_atomic(&attr_args);
3598
2
      break;
3599
0
    case BGP_ATTR_AGGREGATOR:
3600
0
      ret = bgp_attr_aggregator(&attr_args);
3601
0
      break;
3602
2
    case BGP_ATTR_AS4_AGGREGATOR:
3603
2
      ret = bgp_attr_as4_aggregator(&attr_args,
3604
2
                  &as4_aggregator,
3605
2
                  &as4_aggregator_addr);
3606
2
      break;
3607
30
    case BGP_ATTR_COMMUNITIES:
3608
30
      ret = bgp_attr_community(&attr_args);
3609
30
      break;
3610
14
    case BGP_ATTR_LARGE_COMMUNITIES:
3611
14
      ret = bgp_attr_large_community(&attr_args);
3612
14
      break;
3613
8
    case BGP_ATTR_ORIGINATOR_ID:
3614
8
      ret = bgp_attr_originator_id(&attr_args);
3615
8
      break;
3616
19
    case BGP_ATTR_CLUSTER_LIST:
3617
19
      ret = bgp_attr_cluster_list(&attr_args);
3618
19
      break;
3619
121
    case BGP_ATTR_MP_REACH_NLRI:
3620
121
      ret = bgp_mp_reach_parse(&attr_args, mp_update);
3621
121
      break;
3622
12
    case BGP_ATTR_MP_UNREACH_NLRI:
3623
12
      ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw);
3624
12
      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
1
    case BGP_ATTR_PMSI_TUNNEL:
3638
1
      ret = bgp_attr_pmsi_tunnel(&attr_args);
3639
1
      break;
3640
28
    case BGP_ATTR_IPV6_EXT_COMMUNITIES:
3641
28
      ret = bgp_attr_ipv6_ext_communities(&attr_args);
3642
28
      break;
3643
0
    case BGP_ATTR_OTC:
3644
0
      ret = bgp_attr_otc(&attr_args);
3645
0
      break;
3646
1
    case BGP_ATTR_AIGP:
3647
1
      ret = bgp_attr_aigp(&attr_args);
3648
1
      break;
3649
229
    default:
3650
229
      ret = bgp_attr_unknown(&attr_args);
3651
229
      break;
3652
860
    }
3653
3654
860
    if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) {
3655
57
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3656
57
          BGP_NOTIFY_UPDATE_MAL_ATTR);
3657
57
      ret = BGP_ATTR_PARSE_ERROR;
3658
57
      goto done;
3659
57
    }
3660
3661
803
    if (ret == BGP_ATTR_PARSE_EOR) {
3662
49
      goto done;
3663
49
    }
3664
3665
754
    if (ret == BGP_ATTR_PARSE_ERROR) {
3666
3
      flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR,
3667
3
          "%s: Attribute %s, parse error", peer->host,
3668
3
          lookup_msg(attr_str, type, NULL));
3669
3
      goto done;
3670
3
    }
3671
751
    if (ret == BGP_ATTR_PARSE_WITHDRAW) {
3672
53
      flog_warn(
3673
53
        EC_BGP_ATTRIBUTE_PARSE_WITHDRAW,
3674
53
        "%s: Attribute %s, parse error - treating as withdrawal",
3675
53
        peer->host, lookup_msg(attr_str, type, NULL));
3676
53
      stream_forward_getp(BGP_INPUT(peer), endp - BGP_INPUT_PNT(peer));
3677
53
      goto done;
3678
53
    }
3679
3680
    /* Check the fetched length. */
3681
698
    if (BGP_INPUT_PNT(peer) != attr_endp) {
3682
0
      flog_warn(EC_BGP_ATTRIBUTE_FETCH_ERROR,
3683
0
          "%s: BGP attribute %s, fetch error",
3684
0
          peer->host, lookup_msg(attr_str, type, NULL));
3685
0
      bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
3686
0
          BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
3687
0
      ret = BGP_ATTR_PARSE_ERROR;
3688
0
      goto done;
3689
0
    }
3690
698
  }
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
98
  if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST)
3701
98
    attr->label_index = BGP_INVALID_LABEL_INDEX;
3702
3703
  /* Check final read pointer is same as end pointer. */
3704
98
  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
98
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
3729
1
      && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
3730
1
    if (bgp_attr_nexthop_valid(peer, attr) < 0) {
3731
0
      ret = BGP_ATTR_PARSE_ERROR;
3732
0
      goto done;
3733
0
    }
3734
1
  }
3735
3736
  /* Check all mandatory well-known attributes are present */
3737
98
  ret = bgp_attr_check(peer, attr);
3738
98
  if (ret < 0)
3739
36
    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
62
  if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))
3758
56
      && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator,
3759
56
          &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
62
  if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
3771
56
    ret = bgp_attr_aspath_check(peer, attr);
3772
56
    if (ret != BGP_ATTR_PARSE_PROCEED)
3773
0
      goto done;
3774
56
  }
3775
3776
62
  ret = BGP_ATTR_PARSE_PROCEED;
3777
401
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
401
  aspath_unintern(&as4_path);
3791
3792
401
  transit = bgp_attr_get_transit(attr);
3793
401
  if (ret != BGP_ATTR_PARSE_ERROR) {
3794
    /* Finally intern unknown attribute. */
3795
230
    if (transit)
3796
50
      bgp_attr_set_transit(attr, transit_intern(transit));
3797
230
    if (attr->encap_subtlvs)
3798
7
      attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
3799
7
                 ENCAP_SUBTLV_TYPE);
3800
230
#ifdef ENABLE_BGP_VNC
3801
230
    struct bgp_attr_encap_subtlv *vnc_subtlvs =
3802
230
      bgp_attr_get_vnc_subtlvs(attr);
3803
3804
230
    if (vnc_subtlvs)
3805
0
      bgp_attr_set_vnc_subtlvs(
3806
0
        attr,
3807
0
        encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
3808
230
#endif
3809
230
  } else {
3810
171
    if (transit) {
3811
11
      transit_free(transit);
3812
11
      bgp_attr_set_transit(attr, NULL);
3813
11
    }
3814
3815
171
    bgp_attr_flush_encap(attr);
3816
171
  };
3817
3818
  /* Sanity checks */
3819
401
  transit = bgp_attr_get_transit(attr);
3820
401
  if (transit)
3821
50
    assert(transit->refcnt > 0);
3822
401
  if (attr->encap_subtlvs)
3823
7
    assert(attr->encap_subtlvs->refcnt > 0);
3824
401
#ifdef ENABLE_BGP_VNC
3825
401
  struct bgp_attr_encap_subtlv *vnc_subtlvs =
3826
401
    bgp_attr_get_vnc_subtlvs(attr);
3827
3828
401
  if (vnc_subtlvs)
3829
0
    assert(vnc_subtlvs->refcnt > 0);
3830
401
#endif
3831
3832
401
  return ret;
3833
401
}
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
108
{
3841
108
  struct ecommunity *ecom;
3842
108
  uint32_t i;
3843
3844
108
  if (!attr)
3845
0
    return;
3846
3847
108
  ecom = bgp_attr_get_ecommunity(attr);
3848
108
  if (!ecom || !ecom->size)
3849
0
    return;
3850
3851
10.8k
  for (i = 0; i < ecom->size; i++) {
3852
10.7k
    uint8_t *pnt;
3853
10.7k
    uint8_t type, sub_type;
3854
3855
10.7k
    pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
3856
10.7k
    type = pnt[0];
3857
10.7k
    sub_type = pnt[1];
3858
10.7k
    if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
3859
216
          sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
3860
10.7k
      continue;
3861
1
    *tunnel_type = ((pnt[6] << 8) | pnt[7]);
3862
1
    return;
3863
10.7k
  }
3864
3865
107
  return;
3866
108
}
3867
3868
size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
3869
             safi_t safi, struct bpacket_attr_vec_arr *vecarr,
3870
             struct attr *attr)
3871
0
{
3872
0
  size_t sizep;
3873
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
3874
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
3875
0
  afi_t nh_afi;
3876
3877
  /* Set extended bit always to encode the attribute length as 2 bytes */
3878
0
  stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
3879
0
  stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
3880
0
  sizep = stream_get_endp(s);
3881
0
  stream_putw(s, 0); /* Marker: Attribute length. */
3882
3883
3884
  /* Convert AFI, SAFI to values for packet. */
3885
0
  bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
3886
3887
0
  stream_putw(s, pkt_afi);  /* AFI */
3888
0
  stream_putc(s, pkt_safi); /* SAFI */
3889
3890
  /* Nexthop AFI */
3891
0
  if (afi == AFI_IP
3892
0
      && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST
3893
0
    || safi == SAFI_MPLS_VPN || safi == SAFI_MULTICAST))
3894
0
    nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
3895
0
  else if (safi == SAFI_FLOWSPEC)
3896
0
    nh_afi = afi;
3897
0
  else
3898
0
    nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
3899
3900
  /* Nexthop */
3901
0
  bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr);
3902
0
  switch (nh_afi) {
3903
0
  case AFI_IP:
3904
0
    switch (safi) {
3905
0
    case SAFI_UNICAST:
3906
0
    case SAFI_MULTICAST:
3907
0
    case SAFI_LABELED_UNICAST:
3908
0
      stream_putc(s, 4);
3909
0
      stream_put_ipv4(s, attr->nexthop.s_addr);
3910
0
      break;
3911
0
    case SAFI_MPLS_VPN:
3912
0
      stream_putc(s, 12);
3913
0
      stream_putl(s, 0); /* RD = 0, per RFC */
3914
0
      stream_putl(s, 0);
3915
0
      stream_put(s, &attr->mp_nexthop_global_in, 4);
3916
0
      break;
3917
0
    case SAFI_ENCAP:
3918
0
    case SAFI_EVPN:
3919
0
      stream_putc(s, 4);
3920
0
      stream_put(s, &attr->mp_nexthop_global_in, 4);
3921
0
      break;
3922
0
    case SAFI_FLOWSPEC:
3923
0
      if (attr->mp_nexthop_len == 0)
3924
0
        stream_putc(s, 0); /* no nexthop for flowspec */
3925
0
      else {
3926
0
        stream_putc(s, attr->mp_nexthop_len);
3927
0
        stream_put_ipv4(s, attr->nexthop.s_addr);
3928
0
      }
3929
0
      break;
3930
0
    case SAFI_UNSPEC:
3931
0
    case SAFI_MAX:
3932
0
      assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3933
0
      break;
3934
0
    }
3935
0
    break;
3936
0
  case AFI_IP6:
3937
0
    switch (safi) {
3938
0
    case SAFI_UNICAST:
3939
0
    case SAFI_MULTICAST:
3940
0
    case SAFI_LABELED_UNICAST:
3941
0
    case SAFI_EVPN: {
3942
0
      if (attr->mp_nexthop_len
3943
0
          == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3944
0
        stream_putc(s,
3945
0
              BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
3946
0
        stream_put(s, &attr->mp_nexthop_global,
3947
0
             IPV6_MAX_BYTELEN);
3948
0
        stream_put(s, &attr->mp_nexthop_local,
3949
0
             IPV6_MAX_BYTELEN);
3950
0
      } else {
3951
0
        stream_putc(s, IPV6_MAX_BYTELEN);
3952
0
        stream_put(s, &attr->mp_nexthop_global,
3953
0
             IPV6_MAX_BYTELEN);
3954
0
      }
3955
0
    } break;
3956
0
    case SAFI_MPLS_VPN: {
3957
0
      if (attr->mp_nexthop_len ==
3958
0
          BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
3959
0
        stream_putc(s, attr->mp_nexthop_len);
3960
0
      else
3961
0
        stream_putc(s, BGP_ATTR_NHLEN_VPNV6_GLOBAL);
3962
0
      stream_putl(s, 0); /* RD = 0, per RFC */
3963
0
      stream_putl(s, 0);
3964
0
      stream_put(s, &attr->mp_nexthop_global,
3965
0
           IPV6_MAX_BYTELEN);
3966
0
      if (attr->mp_nexthop_len ==
3967
0
          BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
3968
0
        stream_putl(s, 0); /* RD = 0, per RFC */
3969
0
        stream_putl(s, 0);
3970
0
        stream_put(s, &attr->mp_nexthop_local,
3971
0
             IPV6_MAX_BYTELEN);
3972
0
      }
3973
0
    } break;
3974
0
    case SAFI_ENCAP:
3975
0
      stream_putc(s, IPV6_MAX_BYTELEN);
3976
0
      stream_put(s, &attr->mp_nexthop_global,
3977
0
           IPV6_MAX_BYTELEN);
3978
0
      break;
3979
0
    case SAFI_FLOWSPEC:
3980
0
      stream_putc(s, 0); /* no nexthop for flowspec */
3981
0
      break;
3982
0
    case SAFI_UNSPEC:
3983
0
    case SAFI_MAX:
3984
0
      assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
3985
0
      break;
3986
0
    }
3987
0
    break;
3988
0
  case AFI_L2VPN:
3989
0
    if (safi != SAFI_FLOWSPEC)
3990
0
      flog_err(
3991
0
        EC_BGP_ATTR_NH_SEND_LEN,
3992
0
        "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
3993
0
        peer->host, afi, safi, attr->mp_nexthop_len);
3994
0
    break;
3995
0
  case AFI_UNSPEC:
3996
0
  case AFI_MAX:
3997
0
    assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
3998
0
    break;
3999
0
  }
4000
4001
  /* SNPA */
4002
0
  stream_putc(s, 0);
4003
0
  return sizep;
4004
0
}
4005
4006
void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
4007
            const struct prefix *p,
4008
            const struct prefix_rd *prd, mpls_label_t *label,
4009
            uint32_t num_labels, bool addpath_capable,
4010
            uint32_t addpath_tx_id, struct attr *attr)
4011
0
{
4012
0
  switch (safi) {
4013
0
  case SAFI_UNSPEC:
4014
0
  case SAFI_MAX:
4015
0
    assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
4016
0
    break;
4017
0
  case SAFI_MPLS_VPN:
4018
0
    if (addpath_capable)
4019
0
      stream_putl(s, addpath_tx_id);
4020
    /* Label, RD, Prefix write. */
4021
0
    stream_putc(s, p->prefixlen + 88);
4022
0
    stream_put(s, label, BGP_LABEL_BYTES);
4023
0
    stream_put(s, prd->val, 8);
4024
0
    stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
4025
0
    break;
4026
0
  case SAFI_EVPN:
4027
0
    if (afi == AFI_L2VPN)
4028
      /* EVPN prefix - contents depend on type */
4029
0
      bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
4030
0
                 attr, addpath_capable,
4031
0
                 addpath_tx_id);
4032
0
    else
4033
0
      assert(!"Add encoding bits here for other AFI's");
4034
0
    break;
4035
0
  case SAFI_LABELED_UNICAST:
4036
    /* Prefix write with label. */
4037
0
    stream_put_labeled_prefix(s, p, label, addpath_capable,
4038
0
            addpath_tx_id);
4039
0
    break;
4040
0
  case SAFI_FLOWSPEC:
4041
0
    stream_putc(s, p->u.prefix_flowspec.prefixlen);
4042
0
    stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
4043
0
         p->u.prefix_flowspec.prefixlen);
4044
0
    break;
4045
4046
0
  case SAFI_UNICAST:
4047
0
  case SAFI_MULTICAST:
4048
0
    stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
4049
0
    break;
4050
0
  case SAFI_ENCAP:
4051
0
    assert(!"Please add proper encoding of SAFI_ENCAP");
4052
0
    break;
4053
0
  }
4054
0
}
4055
4056
size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
4057
             const struct prefix *p)
4058
0
{
4059
0
  int size = PSIZE(p->prefixlen);
4060
4061
0
  switch (safi) {
4062
0
  case SAFI_UNSPEC:
4063
0
  case SAFI_MAX:
4064
0
    assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
4065
0
    break;
4066
0
  case SAFI_UNICAST:
4067
0
  case SAFI_MULTICAST:
4068
0
    break;
4069
0
  case SAFI_MPLS_VPN:
4070
0
    size += 88;
4071
0
    break;
4072
0
  case SAFI_ENCAP:
4073
    /* This has to be wrong, but I don't know what to put here */
4074
0
    assert(!"Do we try to use this?");
4075
0
    break;
4076
0
  case SAFI_LABELED_UNICAST:
4077
0
    size += BGP_LABEL_BYTES;
4078
0
    break;
4079
0
  case SAFI_EVPN:
4080
    /*
4081
     * TODO: Maximum possible for type-2, type-3 and type-5
4082
     */
4083
0
    if (afi == AFI_L2VPN)
4084
0
      size += 232;
4085
0
    else
4086
0
      assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
4087
0
    break;
4088
0
  case SAFI_FLOWSPEC:
4089
0
    size = ((struct prefix_fs *)p)->prefix.prefixlen;
4090
0
    break;
4091
0
  }
4092
4093
0
  return size;
4094
0
}
4095
4096
/*
4097
 * Encodes the tunnel encapsulation attribute,
4098
 * and with ENABLE_BGP_VNC the VNC attribute which uses
4099
 * almost the same TLV format
4100
 */
4101
static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
4102
          struct stream *s, struct attr *attr,
4103
          uint8_t attrtype)
4104
0
{
4105
0
  unsigned int attrlenfield = 0;
4106
0
  unsigned int attrhdrlen = 0;
4107
0
  struct bgp_attr_encap_subtlv *subtlvs;
4108
0
  struct bgp_attr_encap_subtlv *st;
4109
0
  const char *attrname;
4110
4111
0
  if (!attr || (attrtype == BGP_ATTR_ENCAP
4112
0
          && (!attr->encap_tunneltype
4113
0
        || attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS)))
4114
0
    return;
4115
4116
0
  switch (attrtype) {
4117
0
  case BGP_ATTR_ENCAP:
4118
0
    attrname = "Tunnel Encap";
4119
0
    subtlvs = attr->encap_subtlvs;
4120
0
    if (subtlvs == NULL) /* nothing to do */
4121
0
      return;
4122
    /*
4123
     * The tunnel encap attr has an "outer" tlv.
4124
     * T = tunneltype,
4125
     * L = total length of subtlvs,
4126
     * V = concatenated subtlvs.
4127
     */
4128
0
    attrlenfield = 2 + 2; /* T + L */
4129
0
    attrhdrlen = 1 + 1;   /* subTLV T + L */
4130
0
    break;
4131
4132
#ifdef ENABLE_BGP_VNC_ATTR
4133
  case BGP_ATTR_VNC:
4134
    attrname = "VNC";
4135
    subtlvs = bgp_attr_get_vnc_subtlvs(attr);
4136
    if (subtlvs == NULL) /* nothing to do */
4137
      return;
4138
    attrlenfield = 0;   /* no outer T + L */
4139
    attrhdrlen = 2 + 2; /* subTLV T + L */
4140
    break;
4141
#endif
4142
4143
0
  default:
4144
0
    assert(0);
4145
0
  }
4146
4147
  /* compute attr length */
4148
0
  for (st = subtlvs; st; st = st->next) {
4149
0
    attrlenfield += (attrhdrlen + st->length);
4150
0
  }
4151
4152
0
  if (attrlenfield > 0xffff) {
4153
0
    zlog_info("%s attribute is too long (length=%d), can't send it",
4154
0
        attrname, attrlenfield);
4155
0
    return;
4156
0
  }
4157
4158
0
  if (attrlenfield > 0xff) {
4159
    /* 2-octet length field */
4160
0
    stream_putc(s,
4161
0
          BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4162
0
            | BGP_ATTR_FLAG_EXTLEN);
4163
0
    stream_putc(s, attrtype);
4164
0
    stream_putw(s, attrlenfield & 0xffff);
4165
0
  } else {
4166
    /* 1-octet length field */
4167
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
4168
0
    stream_putc(s, attrtype);
4169
0
    stream_putc(s, attrlenfield & 0xff);
4170
0
  }
4171
4172
0
  if (attrtype == BGP_ATTR_ENCAP) {
4173
    /* write outer T+L */
4174
0
    stream_putw(s, attr->encap_tunneltype);
4175
0
    stream_putw(s, attrlenfield - 4);
4176
0
  }
4177
4178
  /* write each sub-tlv */
4179
0
  for (st = subtlvs; st; st = st->next) {
4180
0
    if (attrtype == BGP_ATTR_ENCAP) {
4181
0
      stream_putc(s, st->type);
4182
0
      stream_putc(s, st->length);
4183
0
#ifdef ENABLE_BGP_VNC
4184
0
    } else {
4185
0
      stream_putw(s, st->type);
4186
0
      stream_putw(s, st->length);
4187
0
#endif
4188
0
    }
4189
0
    stream_put(s, st->value, st->length);
4190
0
  }
4191
0
}
4192
4193
void bgp_packet_mpattr_end(struct stream *s, size_t sizep)
4194
0
{
4195
  /* Set MP attribute length. Don't count the (2) bytes used to encode
4196
     the attr length */
4197
0
  stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2);
4198
0
}
4199
4200
static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
4201
0
{
4202
0
  if (!BGP_AS_IS_PRIVATE(peer->local_as)
4203
0
      || (BGP_AS_IS_PRIVATE(peer->local_as)
4204
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4205
0
             PEER_FLAG_REMOVE_PRIVATE_AS)
4206
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4207
0
             PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
4208
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4209
0
             PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
4210
0
    && !CHECK_FLAG(peer->af_flags[afi][safi],
4211
0
             PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)))
4212
0
    return true;
4213
0
  return false;
4214
0
}
4215
4216
/* Make attribute packet. */
4217
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
4218
        struct stream *s, struct attr *attr,
4219
        struct bpacket_attr_vec_arr *vecarr,
4220
        struct prefix *p, afi_t afi, safi_t safi,
4221
        struct peer *from, struct prefix_rd *prd,
4222
        mpls_label_t *label, uint32_t num_labels,
4223
        bool addpath_capable, uint32_t addpath_tx_id,
4224
        struct bgp_path_info *bpi)
4225
0
{
4226
0
  size_t cp;
4227
0
  size_t aspath_sizep;
4228
0
  struct aspath *aspath;
4229
0
  int send_as4_path = 0;
4230
0
  int send_as4_aggregator = 0;
4231
0
  bool use32bit = CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
4232
0
      && CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV);
4233
4234
0
  if (!bgp)
4235
0
    bgp = peer->bgp;
4236
4237
  /* Remember current pointer. */
4238
0
  cp = stream_get_endp(s);
4239
4240
0
  if (p
4241
0
      && !((afi == AFI_IP && safi == SAFI_UNICAST)
4242
0
     && !peer_cap_enhe(peer, afi, safi))) {
4243
0
    size_t mpattrlen_pos = 0;
4244
4245
0
    mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
4246
0
              vecarr, attr);
4247
0
    bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
4248
0
           num_labels, addpath_capable,
4249
0
           addpath_tx_id, attr);
4250
0
    bgp_packet_mpattr_end(s, mpattrlen_pos);
4251
0
  }
4252
4253
  /* Origin attribute. */
4254
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS);
4255
0
  stream_putc(s, BGP_ATTR_ORIGIN);
4256
0
  stream_putc(s, 1);
4257
0
  stream_putc(s, attr->origin);
4258
4259
  /* AS path attribute. */
4260
4261
  /* If remote-peer is EBGP */
4262
0
  if (peer->sort == BGP_PEER_EBGP
4263
0
      && (!CHECK_FLAG(peer->af_flags[afi][safi],
4264
0
          PEER_FLAG_AS_PATH_UNCHANGED)
4265
0
    || attr->aspath->segments == NULL)
4266
0
      && (!CHECK_FLAG(peer->af_flags[afi][safi],
4267
0
          PEER_FLAG_RSERVER_CLIENT))) {
4268
0
    aspath = aspath_dup(attr->aspath);
4269
4270
    /* Even though we may not be configured for confederations we
4271
     * may have
4272
     * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */
4273
0
    aspath = aspath_delete_confed_seq(aspath);
4274
4275
0
    if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
4276
      /* A confed member, so we need to do the
4277
       * AS_CONFED_SEQUENCE thing if it's outside a common
4278
       * administration.
4279
       * Configured confederation peers MUST be validated
4280
       * under BGP_PEER_CONFED, but if we have configured
4281
       * remote-as as AS_EXTERNAL, we need to check again
4282
       * if the peer belongs to us.
4283
       */
4284
0
      if (bgp_confederation_peers_check(bgp, peer->as)) {
4285
0
        aspath = aspath_add_confed_seq(aspath,
4286
0
                     peer->local_as);
4287
0
      } else {
4288
        /* Stuff our path CONFED_ID on the front */
4289
0
        aspath = aspath_add_seq(aspath, bgp->confed_id);
4290
0
      }
4291
0
    } else {
4292
0
      if (peer->change_local_as) {
4293
        /* If replace-as is specified, we only use the
4294
           change_local_as when
4295
           advertising routes. */
4296
0
        if (!CHECK_FLAG(peer->flags,
4297
0
            PEER_FLAG_LOCAL_AS_REPLACE_AS))
4298
0
          if (bgp_append_local_as(peer, afi,
4299
0
                safi))
4300
0
            aspath = aspath_add_seq(
4301
0
              aspath, peer->local_as);
4302
0
        aspath = aspath_add_seq(aspath,
4303
0
              peer->change_local_as);
4304
0
      } else {
4305
0
        aspath = aspath_add_seq(aspath, peer->local_as);
4306
0
      }
4307
0
    }
4308
0
  } else if (peer->sort == BGP_PEER_CONFED) {
4309
    /* A confed member, so we need to do the AS_CONFED_SEQUENCE
4310
     * thing */
4311
0
    aspath = aspath_dup(attr->aspath);
4312
0
    aspath = aspath_add_confed_seq(aspath, peer->local_as);
4313
0
  } else
4314
0
    aspath = attr->aspath;
4315
4316
  /* If peer is not AS4 capable, then:
4317
   * - send the created AS_PATH out as AS4_PATH (optional, transitive),
4318
   *   but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path
4319
   * segment
4320
   *   types are in it (i.e. exclude them if they are there)
4321
   *   AND do this only if there is at least one asnum > 65535 in the
4322
   * path!
4323
   * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and
4324
   * change
4325
   *   all ASnums > 65535 to BGP_AS_TRANS
4326
   */
4327
4328
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4329
0
  stream_putc(s, BGP_ATTR_AS_PATH);
4330
0
  aspath_sizep = stream_get_endp(s);
4331
0
  stream_putw(s, 0);
4332
0
  stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, use32bit));
4333
4334
  /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs
4335
   * in the path
4336
   */
4337
0
  if (!use32bit && aspath_has_as4(aspath))
4338
0
    send_as4_path =
4339
0
      1; /* we'll do this later, at the correct place */
4340
4341
  /* Nexthop attribute. */
4342
0
  if (afi == AFI_IP && safi == SAFI_UNICAST
4343
0
      && !peer_cap_enhe(peer, afi, safi)) {
4344
0
    afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
4345
4346
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
4347
0
      stream_putc(s, BGP_ATTR_FLAG_TRANS);
4348
0
      stream_putc(s, BGP_ATTR_NEXT_HOP);
4349
0
      bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4350
0
                 attr);
4351
0
      stream_putc(s, 4);
4352
0
      stream_put_ipv4(s, attr->nexthop.s_addr);
4353
0
    } else if (peer_cap_enhe(from, afi, safi)
4354
0
         || (nh_afi == AFI_IP6)) {
4355
      /*
4356
       * Likely this is the case when an IPv4 prefix was
4357
       * received with Extended Next-hop capability in this
4358
       * or another vrf and is now being advertised to
4359
       * non-ENHE peers. Since peer_cap_enhe only checks
4360
       * peers in this vrf, also check the nh_afi to catch
4361
       * the case where the originator was in another vrf.
4362
       * Setting the mandatory (ipv4) next-hop attribute here
4363
       * to enable implicit next-hop self with correct A-F
4364
       * (ipv4 address family).
4365
       */
4366
0
      stream_putc(s, BGP_ATTR_FLAG_TRANS);
4367
0
      stream_putc(s, BGP_ATTR_NEXT_HOP);
4368
0
      bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
4369
0
                 NULL);
4370
0
      stream_putc(s, 4);
4371
0
      stream_put_ipv4(s, 0);
4372
0
    }
4373
0
  }
4374
4375
  /* MED attribute. */
4376
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
4377
0
      || bgp->maxmed_active) {
4378
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4379
0
    stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4380
0
    stream_putc(s, 4);
4381
0
    stream_putl(s, (bgp->maxmed_active ? bgp->maxmed_value
4382
0
               : attr->med));
4383
0
  }
4384
4385
  /* Local preference. */
4386
0
  if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) {
4387
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4388
0
    stream_putc(s, BGP_ATTR_LOCAL_PREF);
4389
0
    stream_putc(s, 4);
4390
0
    stream_putl(s, attr->local_pref);
4391
0
  }
4392
4393
  /* Atomic aggregate. */
4394
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4395
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4396
0
    stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4397
0
    stream_putc(s, 0);
4398
0
  }
4399
4400
  /* Aggregator. */
4401
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4402
    /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
4403
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4404
0
    stream_putc(s, BGP_ATTR_AGGREGATOR);
4405
4406
0
    if (use32bit) {
4407
      /* AS4 capable peer */
4408
0
      stream_putc(s, 8);
4409
0
      stream_putl(s, attr->aggregator_as);
4410
0
    } else {
4411
      /* 2-byte AS peer */
4412
0
      stream_putc(s, 6);
4413
4414
      /* Is ASN representable in 2-bytes? Or must AS_TRANS be
4415
       * used? */
4416
0
      if (attr->aggregator_as > UINT16_MAX) {
4417
0
        stream_putw(s, BGP_AS_TRANS);
4418
4419
        /* we have to send AS4_AGGREGATOR, too.
4420
         * we'll do that later in order to send
4421
         * attributes in ascending
4422
         * order.
4423
         */
4424
0
        send_as4_aggregator = 1;
4425
0
      } else
4426
0
        stream_putw(s, (uint16_t)attr->aggregator_as);
4427
0
    }
4428
0
    stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4429
0
  }
4430
4431
  /* Community attribute. */
4432
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
4433
0
      && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
4434
0
    struct community *comm = NULL;
4435
4436
0
    comm = bgp_attr_get_community(attr);
4437
0
    if (comm->size * 4 > 255) {
4438
0
      stream_putc(s,
4439
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4440
0
              | BGP_ATTR_FLAG_EXTLEN);
4441
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4442
0
      stream_putw(s, comm->size * 4);
4443
0
    } else {
4444
0
      stream_putc(s,
4445
0
            BGP_ATTR_FLAG_OPTIONAL
4446
0
              | BGP_ATTR_FLAG_TRANS);
4447
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4448
0
      stream_putc(s, comm->size * 4);
4449
0
    }
4450
0
    stream_put(s, comm->val, comm->size * 4);
4451
0
  }
4452
4453
  /*
4454
   * Large Community attribute.
4455
   */
4456
0
  if (CHECK_FLAG(peer->af_flags[afi][safi],
4457
0
           PEER_FLAG_SEND_LARGE_COMMUNITY)
4458
0
      && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
4459
0
    if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
4460
0
      stream_putc(s,
4461
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4462
0
              | BGP_ATTR_FLAG_EXTLEN);
4463
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4464
0
      stream_putw(s,
4465
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4466
0
    } else {
4467
0
      stream_putc(s,
4468
0
            BGP_ATTR_FLAG_OPTIONAL
4469
0
              | BGP_ATTR_FLAG_TRANS);
4470
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4471
0
      stream_putc(s,
4472
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4473
0
    }
4474
0
    stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4475
0
         lcom_length(bgp_attr_get_lcommunity(attr)));
4476
0
  }
4477
4478
  /* Route Reflector. */
4479
0
  if (peer->sort == BGP_PEER_IBGP && from
4480
0
      && from->sort == BGP_PEER_IBGP) {
4481
0
    struct cluster_list *cluster = bgp_attr_get_cluster(attr);
4482
4483
    /* Originator ID. */
4484
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4485
0
    stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
4486
0
    stream_putc(s, 4);
4487
4488
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
4489
0
      stream_put_in_addr(s, &attr->originator_id);
4490
0
    else
4491
0
      stream_put_in_addr(s, &from->remote_id);
4492
4493
    /* Cluster list. */
4494
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4495
0
    stream_putc(s, BGP_ATTR_CLUSTER_LIST);
4496
4497
0
    if (cluster) {
4498
0
      stream_putc(s, cluster->length + 4);
4499
      /* If this peer configuration's parent BGP has
4500
       * cluster_id. */
4501
0
      if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4502
0
        stream_put_in_addr(s, &bgp->cluster_id);
4503
0
      else
4504
0
        stream_put_in_addr(s, &bgp->router_id);
4505
0
      stream_put(s, cluster->list, cluster->length);
4506
0
    } else {
4507
0
      stream_putc(s, 4);
4508
      /* If this peer configuration's parent BGP has
4509
       * cluster_id. */
4510
0
      if (bgp->config & BGP_CONFIG_CLUSTER_ID)
4511
0
        stream_put_in_addr(s, &bgp->cluster_id);
4512
0
      else
4513
0
        stream_put_in_addr(s, &bgp->router_id);
4514
0
    }
4515
0
  }
4516
4517
  /* Extended Communities attribute. */
4518
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
4519
0
      && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4520
0
    struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
4521
0
    bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
4522
0
                PEER_FLAG_RSERVER_CLIENT) &&
4523
0
           from &&
4524
0
           CHECK_FLAG(from->af_flags[afi][safi],
4525
0
                PEER_FLAG_RSERVER_CLIENT);
4526
4527
0
    if (peer->sort == BGP_PEER_IBGP ||
4528
0
        peer->sort == BGP_PEER_CONFED || transparent) {
4529
0
      if (ecomm->size * 8 > 255) {
4530
0
        stream_putc(s,
4531
0
              BGP_ATTR_FLAG_OPTIONAL
4532
0
                | BGP_ATTR_FLAG_TRANS
4533
0
                | BGP_ATTR_FLAG_EXTLEN);
4534
0
        stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4535
0
        stream_putw(s, ecomm->size * 8);
4536
0
      } else {
4537
0
        stream_putc(s,
4538
0
              BGP_ATTR_FLAG_OPTIONAL
4539
0
                | BGP_ATTR_FLAG_TRANS);
4540
0
        stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
4541
0
        stream_putc(s, ecomm->size * 8);
4542
0
      }
4543
0
      stream_put(s, ecomm->val, ecomm->size * 8);
4544
0
    } else {
4545
0
      uint8_t *pnt;
4546
0
      int tbit;
4547
0
      int ecom_tr_size = 0;
4548
0
      uint32_t i;
4549
4550
0
      for (i = 0; i < ecomm->size; i++) {
4551
0
        pnt = ecomm->val + (i * 8);
4552
0
        tbit = *pnt;
4553
4554
0
        if (CHECK_FLAG(tbit,
4555
0
                 ECOMMUNITY_FLAG_NON_TRANSITIVE))
4556
0
          continue;
4557
4558
0
        ecom_tr_size++;
4559
0
      }
4560
4561
0
      if (ecom_tr_size) {
4562
0
        if (ecom_tr_size * 8 > 255) {
4563
0
          stream_putc(
4564
0
            s,
4565
0
            BGP_ATTR_FLAG_OPTIONAL
4566
0
              | BGP_ATTR_FLAG_TRANS
4567
0
              | BGP_ATTR_FLAG_EXTLEN);
4568
0
          stream_putc(s,
4569
0
                BGP_ATTR_EXT_COMMUNITIES);
4570
0
          stream_putw(s, ecom_tr_size * 8);
4571
0
        } else {
4572
0
          stream_putc(
4573
0
            s,
4574
0
            BGP_ATTR_FLAG_OPTIONAL
4575
0
              | BGP_ATTR_FLAG_TRANS);
4576
0
          stream_putc(s,
4577
0
                BGP_ATTR_EXT_COMMUNITIES);
4578
0
          stream_putc(s, ecom_tr_size * 8);
4579
0
        }
4580
4581
0
        for (i = 0; i < ecomm->size; i++) {
4582
0
          pnt = ecomm->val + (i * 8);
4583
0
          tbit = *pnt;
4584
4585
0
          if (CHECK_FLAG(
4586
0
                tbit,
4587
0
                ECOMMUNITY_FLAG_NON_TRANSITIVE))
4588
0
            continue;
4589
4590
0
          stream_put(s, pnt, 8);
4591
0
        }
4592
0
      }
4593
0
    }
4594
0
  }
4595
4596
  /* Label index attribute. */
4597
0
  if (safi == SAFI_LABELED_UNICAST) {
4598
0
    if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4599
0
      uint32_t label_index;
4600
4601
0
      label_index = attr->label_index;
4602
4603
0
      if (label_index != BGP_INVALID_LABEL_INDEX) {
4604
0
        stream_putc(s,
4605
0
              BGP_ATTR_FLAG_OPTIONAL
4606
0
                | BGP_ATTR_FLAG_TRANS);
4607
0
        stream_putc(s, BGP_ATTR_PREFIX_SID);
4608
0
        stream_putc(s, 10);
4609
0
        stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
4610
0
        stream_putw(s,
4611
0
              BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
4612
0
        stream_putc(s, 0); // reserved
4613
0
        stream_putw(s, 0); // flags
4614
0
        stream_putl(s, label_index);
4615
0
      }
4616
0
    }
4617
0
  }
4618
4619
  /* SRv6 Service Information Attribute. */
4620
0
  if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_MPLS_VPN) {
4621
0
    if (attr->srv6_l3vpn) {
4622
0
      uint8_t subtlv_len =
4623
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH
4624
0
        + BGP_ATTR_MIN_LEN
4625
0
        + BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH;
4626
0
      uint8_t tlv_len = subtlv_len + BGP_ATTR_MIN_LEN + 1;
4627
0
      uint8_t attr_len = tlv_len + BGP_ATTR_MIN_LEN;
4628
0
      stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4629
0
                 | BGP_ATTR_FLAG_TRANS);
4630
0
      stream_putc(s, BGP_ATTR_PREFIX_SID);
4631
0
      stream_putc(s, attr_len);
4632
0
      stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE);
4633
0
      stream_putw(s, tlv_len);
4634
0
      stream_putc(s, 0); /* reserved */
4635
0
      stream_putc(s, BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO);
4636
0
      stream_putw(s, subtlv_len);
4637
0
      stream_putc(s, 0);      /* reserved */
4638
0
      stream_put(s, &attr->srv6_l3vpn->sid,
4639
0
           sizeof(attr->srv6_l3vpn->sid)); /* sid */
4640
0
      stream_putc(s, 0);      /* sid_flags */
4641
0
      stream_putw(s,
4642
0
            attr->srv6_l3vpn
4643
0
              ->endpoint_behavior); /* endpoint */
4644
0
      stream_putc(s, 0);      /* reserved */
4645
0
      stream_putc(
4646
0
        s,
4647
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE);
4648
0
      stream_putw(
4649
0
        s,
4650
0
        BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH);
4651
0
      stream_putc(s, attr->srv6_l3vpn->loc_block_len);
4652
0
      stream_putc(s, attr->srv6_l3vpn->loc_node_len);
4653
0
      stream_putc(s, attr->srv6_l3vpn->func_len);
4654
0
      stream_putc(s, attr->srv6_l3vpn->arg_len);
4655
0
      stream_putc(s, attr->srv6_l3vpn->transposition_len);
4656
0
      stream_putc(s, attr->srv6_l3vpn->transposition_offset);
4657
0
    } else if (attr->srv6_vpn) {
4658
0
      stream_putc(s, BGP_ATTR_FLAG_OPTIONAL
4659
0
                 | BGP_ATTR_FLAG_TRANS);
4660
0
      stream_putc(s, BGP_ATTR_PREFIX_SID);
4661
0
      stream_putc(s, 22);     /* tlv len */
4662
0
      stream_putc(s, BGP_PREFIX_SID_VPN_SID);
4663
0
      stream_putw(s, 0x13);   /* tlv len */
4664
0
      stream_putc(s, 0x00);   /* reserved */
4665
0
      stream_putc(s, 0x01);   /* sid_type */
4666
0
      stream_putc(s, 0x00);   /* sif_flags */
4667
0
      stream_put(s, &attr->srv6_vpn->sid,
4668
0
           sizeof(attr->srv6_vpn->sid)); /* sid */
4669
0
    }
4670
0
  }
4671
4672
0
  if (send_as4_path) {
4673
    /* If the peer is NOT As4 capable, AND */
4674
    /* there are ASnums > 65535 in path  THEN
4675
     * give out AS4_PATH */
4676
4677
    /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
4678
     * path segments!
4679
     * Hm, I wonder...  confederation things *should* only be at
4680
     * the beginning of an aspath, right?  Then we should use
4681
     * aspath_delete_confed_seq for this, because it is already
4682
     * there! (JK)
4683
     * Folks, talk to me: what is reasonable here!?
4684
     */
4685
4686
    /* Make sure dup aspath before the modification */
4687
0
    if (aspath == attr->aspath)
4688
0
      aspath = aspath_dup(attr->aspath);
4689
0
    aspath = aspath_delete_confed_seq(aspath);
4690
4691
0
    stream_putc(s,
4692
0
          BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
4693
0
            | BGP_ATTR_FLAG_EXTLEN);
4694
0
    stream_putc(s, BGP_ATTR_AS4_PATH);
4695
0
    aspath_sizep = stream_get_endp(s);
4696
0
    stream_putw(s, 0);
4697
0
    stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, 1));
4698
0
  }
4699
4700
0
  if (aspath != attr->aspath)
4701
0
    aspath_free(aspath);
4702
4703
0
  if (send_as4_aggregator) {
4704
    /* send AS4_AGGREGATOR, at this place */
4705
    /* this section of code moved here in order to ensure the
4706
     * correct
4707
     * *ascending* order of attributes
4708
     */
4709
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4710
0
    stream_putc(s, BGP_ATTR_AS4_AGGREGATOR);
4711
0
    stream_putc(s, 8);
4712
0
    stream_putl(s, attr->aggregator_as);
4713
0
    stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4714
0
  }
4715
4716
0
  if (((afi == AFI_IP || afi == AFI_IP6)
4717
0
       && (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN))
4718
0
      || (afi == AFI_L2VPN && safi == SAFI_EVPN)) {
4719
    /* Tunnel Encap attribute */
4720
0
    bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
4721
4722
#ifdef ENABLE_BGP_VNC_ATTR
4723
    /* VNC attribute */
4724
    bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
4725
#endif
4726
0
  }
4727
4728
  /* PMSI Tunnel */
4729
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
4730
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4731
0
    stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
4732
0
    stream_putc(s, 9); // Length
4733
0
    stream_putc(s, 0); // Flags
4734
0
    stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
4735
0
    stream_put(s, &(attr->label),
4736
0
         BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
4737
0
    stream_put_ipv4(s, attr->nexthop.s_addr);
4738
    // Unicast tunnel endpoint IP address
4739
0
  }
4740
4741
  /* OTC */
4742
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
4743
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4744
0
    stream_putc(s, BGP_ATTR_OTC);
4745
0
    stream_putc(s, 4);
4746
0
    stream_putl(s, attr->otc);
4747
0
  }
4748
4749
  /* AIGP */
4750
0
  if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
4751
0
      (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
4752
0
       peer->sort != BGP_PEER_EBGP)) {
4753
    /* At the moment only AIGP Metric TLV exists for AIGP
4754
     * attribute. If more comes in, do not forget to update
4755
     * attr_len variable to include new ones.
4756
     */
4757
0
    uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
4758
4759
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4760
0
    stream_putc(s, BGP_ATTR_AIGP);
4761
0
    stream_putc(s, attr_len);
4762
0
    stream_put_bgp_aigp_tlv_metric(s, bpi);
4763
0
  }
4764
4765
  /* Unknown transit attribute. */
4766
0
  struct transit *transit = bgp_attr_get_transit(attr);
4767
4768
0
  if (transit)
4769
0
    stream_put(s, transit->val, transit->length);
4770
4771
  /* Return total size of attribute. */
4772
0
  return stream_get_endp(s) - cp;
4773
0
}
4774
4775
size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
4776
0
{
4777
0
  unsigned long attrlen_pnt;
4778
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
4779
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
4780
4781
  /* Set extended bit always to encode the attribute length as 2 bytes */
4782
0
  stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
4783
0
  stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
4784
4785
0
  attrlen_pnt = stream_get_endp(s);
4786
0
  stream_putw(s, 0); /* Length of this attribute. */
4787
4788
  /* Convert AFI, SAFI to values for packet. */
4789
0
  bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
4790
4791
0
  stream_putw(s, pkt_afi);
4792
0
  stream_putc(s, pkt_safi);
4793
4794
0
  return attrlen_pnt;
4795
0
}
4796
4797
void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
4798
         afi_t afi, safi_t safi,
4799
         const struct prefix_rd *prd,
4800
         mpls_label_t *label, uint32_t num_labels,
4801
         bool addpath_capable, uint32_t addpath_tx_id,
4802
         struct attr *attr)
4803
0
{
4804
0
  uint8_t wlabel[4] = {0x80, 0x00, 0x00};
4805
4806
0
  if (safi == SAFI_LABELED_UNICAST) {
4807
0
    label = (mpls_label_t *)wlabel;
4808
0
    num_labels = 1;
4809
0
  }
4810
4811
0
  bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, num_labels,
4812
0
         addpath_capable, addpath_tx_id, attr);
4813
0
}
4814
4815
void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt)
4816
0
{
4817
0
  bgp_packet_mpattr_end(s, attrlen_pnt);
4818
0
}
4819
4820
/* Initialization of attribute. */
4821
void bgp_attr_init(void)
4822
1
{
4823
1
  aspath_init();
4824
1
  attrhash_init();
4825
1
  community_init();
4826
1
  ecommunity_init();
4827
1
  lcommunity_init();
4828
1
  cluster_init();
4829
1
  transit_init();
4830
1
  encap_init();
4831
1
  srv6_init();
4832
1
}
4833
4834
void bgp_attr_finish(void)
4835
0
{
4836
0
  aspath_finish();
4837
0
  attrhash_finish();
4838
0
  community_finish();
4839
0
  ecommunity_finish();
4840
0
  lcommunity_finish();
4841
0
  cluster_finish();
4842
0
  transit_finish();
4843
0
  encap_finish();
4844
0
  srv6_finish();
4845
0
}
4846
4847
/* Make attribute packet. */
4848
void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
4849
        const struct prefix *prefix)
4850
0
{
4851
0
  unsigned long cp;
4852
0
  unsigned long len;
4853
0
  size_t aspath_lenp;
4854
0
  struct aspath *aspath;
4855
0
  bool addpath_capable = false;
4856
0
  uint32_t addpath_tx_id = 0;
4857
0
  struct attr *attr = bpi->attr;
4858
4859
  /* Remember current pointer. */
4860
0
  cp = stream_get_endp(s);
4861
4862
  /* Place holder of length. */
4863
0
  stream_putw(s, 0);
4864
4865
  /* Origin attribute. */
4866
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS);
4867
0
  stream_putc(s, BGP_ATTR_ORIGIN);
4868
0
  stream_putc(s, 1);
4869
0
  stream_putc(s, attr->origin);
4870
4871
0
  aspath = attr->aspath;
4872
4873
0
  stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN);
4874
0
  stream_putc(s, BGP_ATTR_AS_PATH);
4875
0
  aspath_lenp = stream_get_endp(s);
4876
0
  stream_putw(s, 0);
4877
4878
0
  stream_putw_at(s, aspath_lenp, aspath_put(s, aspath, 1));
4879
4880
  /* Nexthop attribute. */
4881
  /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
4882
0
  if (prefix != NULL && prefix->family != AF_INET6) {
4883
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4884
0
    stream_putc(s, BGP_ATTR_NEXT_HOP);
4885
0
    stream_putc(s, 4);
4886
0
    stream_put_ipv4(s, attr->nexthop.s_addr);
4887
0
  }
4888
4889
  /* MED attribute. */
4890
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
4891
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4892
0
    stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
4893
0
    stream_putc(s, 4);
4894
0
    stream_putl(s, attr->med);
4895
0
  }
4896
4897
  /* Local preference. */
4898
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
4899
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4900
0
    stream_putc(s, BGP_ATTR_LOCAL_PREF);
4901
0
    stream_putc(s, 4);
4902
0
    stream_putl(s, attr->local_pref);
4903
0
  }
4904
4905
  /* Atomic aggregate. */
4906
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
4907
0
    stream_putc(s, BGP_ATTR_FLAG_TRANS);
4908
0
    stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
4909
0
    stream_putc(s, 0);
4910
0
  }
4911
4912
  /* Aggregator. */
4913
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
4914
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
4915
0
    stream_putc(s, BGP_ATTR_AGGREGATOR);
4916
0
    stream_putc(s, 8);
4917
0
    stream_putl(s, attr->aggregator_as);
4918
0
    stream_put_ipv4(s, attr->aggregator_addr.s_addr);
4919
0
  }
4920
4921
  /* Community attribute. */
4922
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
4923
0
    struct community *comm = NULL;
4924
4925
0
    comm = bgp_attr_get_community(attr);
4926
0
    if (comm->size * 4 > 255) {
4927
0
      stream_putc(s,
4928
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4929
0
              | BGP_ATTR_FLAG_EXTLEN);
4930
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4931
0
      stream_putw(s, comm->size * 4);
4932
0
    } else {
4933
0
      stream_putc(s,
4934
0
            BGP_ATTR_FLAG_OPTIONAL
4935
0
              | BGP_ATTR_FLAG_TRANS);
4936
0
      stream_putc(s, BGP_ATTR_COMMUNITIES);
4937
0
      stream_putc(s, comm->size * 4);
4938
0
    }
4939
0
    stream_put(s, comm->val, comm->size * 4);
4940
0
  }
4941
4942
  /* Large Community attribute. */
4943
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
4944
0
    if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
4945
0
      stream_putc(s,
4946
0
            BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
4947
0
              | BGP_ATTR_FLAG_EXTLEN);
4948
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4949
0
      stream_putw(s,
4950
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4951
0
    } else {
4952
0
      stream_putc(s,
4953
0
            BGP_ATTR_FLAG_OPTIONAL
4954
0
              | BGP_ATTR_FLAG_TRANS);
4955
0
      stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
4956
0
      stream_putc(s,
4957
0
            lcom_length(bgp_attr_get_lcommunity(attr)));
4958
0
    }
4959
4960
0
    stream_put(s, bgp_attr_get_lcommunity(attr)->val,
4961
0
         lcom_length(bgp_attr_get_lcommunity(attr)));
4962
0
  }
4963
4964
  /* Add a MP_NLRI attribute to dump the IPv6 next hop */
4965
0
  if (prefix != NULL && prefix->family == AF_INET6
4966
0
      && (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
4967
0
    || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)) {
4968
0
    int sizep;
4969
4970
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
4971
0
    stream_putc(s, BGP_ATTR_MP_REACH_NLRI);
4972
0
    sizep = stream_get_endp(s);
4973
4974
    /* MP header */
4975
0
    stream_putc(s, 0);      /* Marker: Attribute length. */
4976
0
    stream_putw(s, AFI_IP6);      /* AFI */
4977
0
    stream_putc(s, SAFI_UNICAST); /* SAFI */
4978
4979
    /* Next hop */
4980
0
    stream_putc(s, attr->mp_nexthop_len);
4981
0
    stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN);
4982
0
    if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
4983
0
      stream_put(s, &attr->mp_nexthop_local,
4984
0
           IPV6_MAX_BYTELEN);
4985
4986
    /* SNPA */
4987
0
    stream_putc(s, 0);
4988
4989
    /* Prefix */
4990
0
    stream_put_prefix_addpath(s, prefix, addpath_capable,
4991
0
            addpath_tx_id);
4992
4993
    /* Set MP attribute length. */
4994
0
    stream_putc_at(s, sizep, (stream_get_endp(s) - sizep) - 1);
4995
0
  }
4996
4997
  /* Prefix SID */
4998
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
4999
0
    if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
5000
0
      stream_putc(s,
5001
0
            BGP_ATTR_FLAG_OPTIONAL
5002
0
              | BGP_ATTR_FLAG_TRANS);
5003
0
      stream_putc(s, BGP_ATTR_PREFIX_SID);
5004
0
      stream_putc(s, 10);
5005
0
      stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
5006
0
      stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
5007
0
      stream_putc(s, 0); // reserved
5008
0
      stream_putw(s, 0); // flags
5009
0
      stream_putl(s, attr->label_index);
5010
0
    }
5011
0
  }
5012
5013
  /* OTC */
5014
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
5015
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5016
0
    stream_putc(s, BGP_ATTR_OTC);
5017
0
    stream_putc(s, 4);
5018
0
    stream_putl(s, attr->otc);
5019
0
  }
5020
5021
  /* AIGP */
5022
0
  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
5023
    /* At the moment only AIGP Metric TLV exists for AIGP
5024
     * attribute. If more comes in, do not forget to update
5025
     * attr_len variable to include new ones.
5026
     */
5027
0
    uint8_t attr_len = BGP_AIGP_TLV_METRIC_LEN;
5028
5029
0
    stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
5030
0
    stream_putc(s, BGP_ATTR_AIGP);
5031
0
    stream_putc(s, attr_len);
5032
0
    stream_put_bgp_aigp_tlv_metric(s, bpi);
5033
0
  }
5034
5035
  /* Return total size of attribute. */
5036
0
  len = stream_get_endp(s) - cp - 2;
5037
0
  stream_putw_at(s, cp, len);
5038
0
}
5039
5040
void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
5041
            const char *discard_attrs, bool set)
5042
0
{
5043
0
  int i, num_attributes;
5044
0
  char **attributes;
5045
0
  afi_t afi;
5046
0
  safi_t safi;
5047
5048
5049
  /* If `no` command specified without arbitrary attributes,
5050
   * then flush all.
5051
   */
5052
0
  if (!discard_attrs) {
5053
0
    for (i = 0; i < BGP_ATTR_MAX; i++)
5054
0
      peer->discard_attrs[i] = false;
5055
0
    goto discard_soft_clear;
5056
0
  }
5057
5058
0
  if (discard_attrs) {
5059
0
    frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
5060
5061
0
    if (set)
5062
0
      for (i = 0; i < BGP_ATTR_MAX; i++)
5063
0
        peer->discard_attrs[i] = false;
5064
5065
0
    for (i = 0; i < num_attributes; i++) {
5066
0
      uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5067
5068
0
      XFREE(MTYPE_TMP, attributes[i]);
5069
5070
      /* Some of the attributes, just can't be ignored. */
5071
0
      if (attr_num == BGP_ATTR_ORIGIN ||
5072
0
          attr_num == BGP_ATTR_AS_PATH ||
5073
0
          attr_num == BGP_ATTR_NEXT_HOP ||
5074
0
          attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5075
0
          attr_num == BGP_ATTR_MP_REACH_NLRI ||
5076
0
          attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5077
0
          attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5078
0
        vty_out(vty,
5079
0
          "%% Can't discard path-attribute %s, ignoring.\n",
5080
0
          lookup_msg(attr_str, attr_num, NULL));
5081
0
        continue;
5082
0
      }
5083
5084
      /* Ignore local-pref, originator-id, cluster-list only
5085
       * for eBGP.
5086
       */
5087
0
      if (peer->sort != BGP_PEER_EBGP &&
5088
0
          (attr_num == BGP_ATTR_LOCAL_PREF ||
5089
0
           attr_num == BGP_ATTR_ORIGINATOR_ID ||
5090
0
           attr_num == BGP_ATTR_CLUSTER_LIST)) {
5091
0
        vty_out(vty,
5092
0
          "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
5093
0
          lookup_msg(attr_str, attr_num, NULL));
5094
0
        continue;
5095
0
      }
5096
5097
0
      peer->discard_attrs[attr_num] = set;
5098
0
    }
5099
0
    XFREE(MTYPE_TMP, attributes);
5100
0
  discard_soft_clear:
5101
    /* Configuring path attributes to be discarded will trigger
5102
     * an inbound Route Refresh to ensure that the routing table
5103
     * is up to date.
5104
     */
5105
0
    FOREACH_AFI_SAFI (afi, safi)
5106
0
      peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5107
0
  }
5108
0
}
5109
5110
void bgp_path_attribute_withdraw_vty(struct vty *vty, struct peer *peer,
5111
             const char *withdraw_attrs, bool set)
5112
0
{
5113
0
  int i, num_attributes;
5114
0
  char **attributes;
5115
0
  afi_t afi;
5116
0
  safi_t safi;
5117
5118
  /* If `no` command specified without arbitrary attributes,
5119
   * then flush all.
5120
   */
5121
0
  if (!withdraw_attrs) {
5122
0
    for (i = 0; i < BGP_ATTR_MAX; i++)
5123
0
      peer->withdraw_attrs[i] = false;
5124
0
    goto withdraw_soft_clear;
5125
0
  }
5126
5127
0
  if (withdraw_attrs) {
5128
0
    frrstr_split(withdraw_attrs, " ", &attributes, &num_attributes);
5129
5130
0
    if (set)
5131
0
      for (i = 0; i < BGP_ATTR_MAX; i++)
5132
0
        peer->withdraw_attrs[i] = false;
5133
5134
0
    for (i = 0; i < num_attributes; i++) {
5135
0
      uint8_t attr_num = strtoul(attributes[i], NULL, 10);
5136
5137
0
      XFREE(MTYPE_TMP, attributes[i]);
5138
5139
      /* Some of the attributes, just can't be ignored. */
5140
0
      if (attr_num == BGP_ATTR_ORIGIN ||
5141
0
          attr_num == BGP_ATTR_AS_PATH ||
5142
0
          attr_num == BGP_ATTR_NEXT_HOP ||
5143
0
          attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
5144
0
          attr_num == BGP_ATTR_MP_REACH_NLRI ||
5145
0
          attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
5146
0
          attr_num == BGP_ATTR_EXT_COMMUNITIES) {
5147
0
        vty_out(vty,
5148
0
          "%% Can't treat-as-withdraw path-attribute %s, ignoring.\n",
5149
0
          lookup_msg(attr_str, attr_num, NULL));
5150
0
        continue;
5151
0
      }
5152
5153
      /* Ignore local-pref, originator-id, cluster-list only
5154
       * for eBGP.
5155
       */
5156
0
      if (peer->sort != BGP_PEER_EBGP &&
5157
0
          (attr_num == BGP_ATTR_LOCAL_PREF ||
5158
0
           attr_num == BGP_ATTR_ORIGINATOR_ID ||
5159
0
           attr_num == BGP_ATTR_CLUSTER_LIST)) {
5160
0
        vty_out(vty,
5161
0
          "%% Can treat-as-withdraw path-attribute %s only for eBGP, ignoring.\n",
5162
0
          lookup_msg(attr_str, attr_num, NULL));
5163
0
        continue;
5164
0
      }
5165
5166
0
      peer->withdraw_attrs[attr_num] = set;
5167
0
    }
5168
0
    XFREE(MTYPE_TMP, attributes);
5169
0
  withdraw_soft_clear:
5170
    /* Configuring path attributes to be treated as withdraw will
5171
     * trigger
5172
     * an inbound Route Refresh to ensure that the routing table
5173
     * is up to date.
5174
     */
5175
0
    FOREACH_AFI_SAFI (afi, safi)
5176
0
      peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
5177
0
  }
5178
0
}
5179
5180
enum bgp_attr_parse_ret bgp_attr_ignore(struct peer *peer, uint8_t type)
5181
1
{
5182
1
  bool discard = peer->discard_attrs[type];
5183
1
  bool withdraw = peer->withdraw_attrs[type];
5184
5185
1
  if (bgp_debug_update(peer, NULL, NULL, 1) && (discard || withdraw))
5186
0
    zlog_debug("%pBP: Ignoring attribute %s (%s)", peer,
5187
1
         lookup_msg(attr_str, type, NULL),
5188
1
         withdraw ? "treat-as-withdraw" : "discard");
5189
5190
1
  return withdraw ? BGP_ATTR_PARSE_WITHDRAW : BGP_ATTR_PARSE_PROCEED;
5191
1
}