Coverage Report

Created: 2026-09-14 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_open.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* BGP open message handling
3
 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4
 */
5
6
#include <zebra.h>
7
8
#include "linklist.h"
9
#include "prefix.h"
10
#include "stream.h"
11
#include "frrevent.h"
12
#include "log.h"
13
#include "command.h"
14
#include "memory.h"
15
#include "queue.h"
16
#include "filter.h"
17
18
#include "lib/json.h"
19
#include "bgpd/bgpd.h"
20
#include "bgpd/bgp_attr.h"
21
#include "bgpd/bgp_debug.h"
22
#include "bgpd/bgp_errors.h"
23
#include "bgpd/bgp_fsm.h"
24
#include "bgpd/bgp_packet.h"
25
#include "bgpd/bgp_open.h"
26
#include "bgpd/bgp_aspath.h"
27
#include "bgpd/bgp_vty.h"
28
#include "bgpd/bgp_memory.h"
29
30
static const struct message capcode_str[] = {
31
  {CAPABILITY_CODE_MP, "MultiProtocol Extensions"},
32
  {CAPABILITY_CODE_REFRESH, "Route Refresh"},
33
  {CAPABILITY_CODE_ORF, "Cooperative Route Filtering"},
34
  {CAPABILITY_CODE_RESTART, "Graceful Restart"},
35
  {CAPABILITY_CODE_AS4, "4-octet AS number"},
36
  {CAPABILITY_CODE_ADDPATH, "AddPath"},
37
  {CAPABILITY_CODE_DYNAMIC, "Dynamic"},
38
  {CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"},
39
  {CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"},
40
  {CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"},
41
  {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"},
42
  {CAPABILITY_CODE_FQDN, "FQDN"},
43
  {CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
44
  {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
45
  {CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart"},
46
  {CAPABILITY_CODE_ROLE, "Role"},
47
  {CAPABILITY_CODE_SOFT_VERSION, "Software Version"},
48
  {0}};
49
50
/* Minimum sizes for length field of each cap (so not inc. the header) */
51
static const size_t cap_minsizes[] = {
52
    [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
53
    [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
54
    [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
55
    [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
56
    [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
57
    [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
58
    [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
59
    [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN,
60
    [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN,
61
    [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
62
    [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
63
    [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
64
    [CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
65
    [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
66
    [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
67
    [CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
68
    [CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN,
69
};
70
71
/* value the capability must be a multiple of.
72
 * 0-data capabilities won't be checked against this.
73
 * Other capabilities whose data doesn't fall on convenient boundaries for this
74
 * table should be set to 1.
75
 */
76
static const size_t cap_modsizes[] = {
77
    [CAPABILITY_CODE_MP] = 4,
78
    [CAPABILITY_CODE_REFRESH] = 1,
79
    [CAPABILITY_CODE_ORF] = 1,
80
    [CAPABILITY_CODE_RESTART] = 1,
81
    [CAPABILITY_CODE_AS4] = 4,
82
    [CAPABILITY_CODE_ADDPATH] = 4,
83
    [CAPABILITY_CODE_DYNAMIC] = 1,
84
    [CAPABILITY_CODE_DYNAMIC_OLD] = 1,
85
    [CAPABILITY_CODE_ENHE] = 6,
86
    [CAPABILITY_CODE_REFRESH_OLD] = 1,
87
    [CAPABILITY_CODE_ORF_OLD] = 1,
88
    [CAPABILITY_CODE_FQDN] = 1,
89
    [CAPABILITY_CODE_ENHANCED_RR] = 1,
90
    [CAPABILITY_CODE_EXT_MESSAGE] = 1,
91
    [CAPABILITY_CODE_LLGR] = 1,
92
    [CAPABILITY_CODE_ROLE] = 1,
93
    [CAPABILITY_CODE_SOFT_VERSION] = 1,
94
};
95
96
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
97
   negotiate remote peer supports extentions or not. But if
98
   remote-peer doesn't supports negotiation process itself.  We would
99
   like to do manual configuration.
100
101
   So there is many configurable point.  First of all we want set each
102
   peer whether we send capability negotiation to the peer or not.
103
   Next, if we send capability to the peer we want to set my capability
104
   inforation at each peer. */
105
106
void bgp_capability_vty_out(struct vty *vty, struct peer *peer, bool use_json,
107
          json_object *json_neigh)
108
0
{
109
0
  char *pnt;
110
0
  char *end;
111
0
  struct capability_mp_data mpc;
112
0
  struct capability_header *hdr;
113
0
  json_object *json_cap = NULL;
114
115
0
  if (use_json)
116
0
    json_cap = json_object_new_object();
117
118
0
  pnt = peer->notify.data;
119
0
  end = pnt + peer->notify.length;
120
121
0
  while (pnt < end) {
122
0
    if (pnt + sizeof(struct capability_mp_data) + 2 > end)
123
0
      return;
124
125
0
    hdr = (struct capability_header *)pnt;
126
0
    if (pnt + hdr->length + 2 > end)
127
0
      return;
128
129
0
    memcpy(&mpc, pnt + 2, sizeof(struct capability_mp_data));
130
131
0
    if (hdr->code == CAPABILITY_CODE_MP) {
132
0
      afi_t afi;
133
0
      safi_t safi;
134
135
0
      (void)bgp_map_afi_safi_iana2int(ntohs(mpc.afi),
136
0
              mpc.safi, &afi, &safi);
137
138
0
      if (use_json) {
139
0
        switch (afi) {
140
0
        case AFI_IP:
141
0
          json_object_string_add(
142
0
            json_cap,
143
0
            "capabilityErrorMultiProtocolAfi",
144
0
            "IPv4");
145
0
          break;
146
0
        case AFI_IP6:
147
0
          json_object_string_add(
148
0
            json_cap,
149
0
            "capabilityErrorMultiProtocolAfi",
150
0
            "IPv6");
151
0
          break;
152
0
        case AFI_L2VPN:
153
0
          json_object_string_add(
154
0
            json_cap,
155
0
            "capabilityErrorMultiProtocolAfi",
156
0
            "L2VPN");
157
0
          break;
158
0
        case AFI_UNSPEC:
159
0
        case AFI_MAX:
160
0
          json_object_int_add(
161
0
            json_cap,
162
0
            "capabilityErrorMultiProtocolAfiUnknown",
163
0
            ntohs(mpc.afi));
164
0
          break;
165
0
        }
166
0
        switch (safi) {
167
0
        case SAFI_UNICAST:
168
0
          json_object_string_add(
169
0
            json_cap,
170
0
            "capabilityErrorMultiProtocolSafi",
171
0
            "unicast");
172
0
          break;
173
0
        case SAFI_MULTICAST:
174
0
          json_object_string_add(
175
0
            json_cap,
176
0
            "capabilityErrorMultiProtocolSafi",
177
0
            "multicast");
178
0
          break;
179
0
        case SAFI_LABELED_UNICAST:
180
0
          json_object_string_add(
181
0
            json_cap,
182
0
            "capabilityErrorMultiProtocolSafi",
183
0
            "labeled-unicast");
184
0
          break;
185
0
        case SAFI_MPLS_VPN:
186
0
          json_object_string_add(
187
0
            json_cap,
188
0
            "capabilityErrorMultiProtocolSafi",
189
0
            "MPLS-labeled VPN");
190
0
          break;
191
0
        case SAFI_ENCAP:
192
0
          json_object_string_add(
193
0
            json_cap,
194
0
            "capabilityErrorMultiProtocolSafi",
195
0
            "encap");
196
0
          break;
197
0
        case SAFI_EVPN:
198
0
          json_object_string_add(
199
0
            json_cap,
200
0
            "capabilityErrorMultiProtocolSafi",
201
0
            "EVPN");
202
0
          break;
203
0
        case SAFI_FLOWSPEC:
204
0
          json_object_string_add(
205
0
            json_cap,
206
0
            "capabilityErrorMultiProtocolSafi",
207
0
            "flowspec");
208
0
          break;
209
0
        case SAFI_UNSPEC:
210
0
        case SAFI_MAX:
211
0
          json_object_int_add(
212
0
            json_cap,
213
0
            "capabilityErrorMultiProtocolSafiUnknown",
214
0
            mpc.safi);
215
0
          break;
216
0
        }
217
0
      } else {
218
0
        vty_out(vty,
219
0
          "  Capability error for: Multi protocol ");
220
0
        switch (afi) {
221
0
        case AFI_IP:
222
0
          vty_out(vty, "AFI IPv4, ");
223
0
          break;
224
0
        case AFI_IP6:
225
0
          vty_out(vty, "AFI IPv6, ");
226
0
          break;
227
0
        case AFI_L2VPN:
228
0
          vty_out(vty, "AFI L2VPN, ");
229
0
          break;
230
0
        case AFI_UNSPEC:
231
0
        case AFI_MAX:
232
0
          vty_out(vty, "AFI Unknown %d, ",
233
0
            ntohs(mpc.afi));
234
0
          break;
235
0
        }
236
0
        switch (safi) {
237
0
        case SAFI_UNICAST:
238
0
          vty_out(vty, "SAFI Unicast");
239
0
          break;
240
0
        case SAFI_MULTICAST:
241
0
          vty_out(vty, "SAFI Multicast");
242
0
          break;
243
0
        case SAFI_LABELED_UNICAST:
244
0
          vty_out(vty, "SAFI Labeled-unicast");
245
0
          break;
246
0
        case SAFI_MPLS_VPN:
247
0
          vty_out(vty, "SAFI MPLS-labeled VPN");
248
0
          break;
249
0
        case SAFI_ENCAP:
250
0
          vty_out(vty, "SAFI ENCAP");
251
0
          break;
252
0
        case SAFI_FLOWSPEC:
253
0
          vty_out(vty, "SAFI FLOWSPEC");
254
0
          break;
255
0
        case SAFI_EVPN:
256
0
          vty_out(vty, "SAFI EVPN");
257
0
          break;
258
0
        case SAFI_UNSPEC:
259
0
        case SAFI_MAX:
260
0
          vty_out(vty, "SAFI Unknown %d ",
261
0
            mpc.safi);
262
0
          break;
263
0
        }
264
0
        vty_out(vty, "\n");
265
0
      }
266
0
    } else if (hdr->code >= 128) {
267
0
      if (use_json)
268
0
        json_object_int_add(
269
0
          json_cap,
270
0
          "capabilityErrorVendorSpecificCapabilityCode",
271
0
          hdr->code);
272
0
      else
273
0
        vty_out(vty,
274
0
          "  Capability error: vendor specific capability code %d",
275
0
          hdr->code);
276
0
    } else {
277
0
      if (use_json)
278
0
        json_object_int_add(
279
0
          json_cap,
280
0
          "capabilityErrorUnknownCapabilityCode",
281
0
          hdr->code);
282
0
      else
283
0
        vty_out(vty,
284
0
          "  Capability error: unknown capability code %d",
285
0
          hdr->code);
286
0
    }
287
0
    pnt += hdr->length + 2;
288
0
  }
289
0
  if (use_json)
290
0
    json_object_object_add(json_neigh, "capabilityErrors",
291
0
               json_cap);
292
0
}
293
294
static void bgp_capability_mp_data(struct stream *s,
295
           struct capability_mp_data *mpc)
296
29
{
297
29
  mpc->afi = stream_getw(s);
298
29
  mpc->reserved = stream_getc(s);
299
29
  mpc->safi = stream_getc(s);
300
29
}
301
302
/* Set negotiated capability value. */
303
static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr)
304
25
{
305
25
  struct capability_mp_data mpc;
306
25
  struct stream *s = BGP_INPUT(peer);
307
25
  afi_t afi;
308
25
  safi_t safi;
309
310
  /* Verify length is 4 */
311
25
  if (hdr->length != 4) {
312
1
    flog_warn(
313
1
      EC_BGP_CAPABILITY_INVALID_LENGTH,
314
1
      "MP Cap: Received invalid length %d, non-multiple of 4",
315
1
      hdr->length);
316
1
    return -1;
317
1
  }
318
319
24
  bgp_capability_mp_data(s, &mpc);
320
321
24
  if (bgp_debug_neighbor_events(peer))
322
0
    zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s",
323
24
         peer->host, lookup_msg(capcode_str, hdr->code, NULL),
324
24
         iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
325
326
  /* Convert AFI, SAFI to internal values, check. */
327
24
  if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi))
328
5
    return -1;
329
330
  /* Now safi remapped, and afi/safi are valid array indices */
331
19
  peer->afc_recv[afi][safi] = 1;
332
333
19
  if (peer->afc[afi][safi])
334
0
    peer->afc_nego[afi][safi] = 1;
335
19
  else
336
19
    return -1;
337
338
0
  return 0;
339
19
}
340
341
static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi,
342
             iana_safi_t safi, uint8_t type,
343
             uint8_t mode)
344
8
{
345
8
  if (bgp_debug_neighbor_events(peer))
346
0
    zlog_debug(
347
8
      "%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
348
8
      peer->host, afi, safi, type, mode);
349
8
}
350
351
static const struct message orf_type_str[] = {
352
  {ORF_TYPE_RESERVED, "Reserved"},
353
  {ORF_TYPE_PREFIX, "Prefixlist"},
354
  {ORF_TYPE_PREFIX_OLD, "Prefixlist (old)"},
355
  {0}};
356
357
static const struct message orf_mode_str[] = {{ORF_MODE_RECEIVE, "Receive"},
358
                {ORF_MODE_SEND, "Send"},
359
                {ORF_MODE_BOTH, "Both"},
360
                {0}};
361
362
static int bgp_capability_orf_entry(struct peer *peer,
363
            struct capability_header *hdr)
364
5
{
365
5
  struct stream *s = BGP_INPUT(peer);
366
5
  struct capability_mp_data mpc;
367
5
  uint8_t num;
368
5
  iana_afi_t pkt_afi;
369
5
  afi_t afi;
370
5
  iana_safi_t pkt_safi;
371
5
  safi_t safi;
372
5
  uint8_t type;
373
5
  uint8_t mode;
374
5
  uint16_t sm_cap = 0; /* capability send-mode receive */
375
5
  uint16_t rm_cap = 0; /* capability receive-mode receive */
376
5
  int i;
377
378
  /* ORF Entry header */
379
5
  bgp_capability_mp_data(s, &mpc);
380
5
  num = stream_getc(s);
381
5
  pkt_afi = mpc.afi;
382
5
  pkt_safi = mpc.safi;
383
384
5
  if (bgp_debug_neighbor_events(peer))
385
0
    zlog_debug("%s ORF Cap entry for afi/safi: %s/%s", peer->host,
386
5
         iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
387
388
  /* Convert AFI, SAFI to internal values, check. */
389
5
  if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
390
3
    zlog_info(
391
3
      "%s Addr-family %d/%d not supported. Ignoring the ORF capability",
392
3
      peer->host, pkt_afi, pkt_safi);
393
3
    return 0;
394
3
  }
395
396
2
  mpc.afi = pkt_afi;
397
2
  mpc.safi = safi;
398
399
  /* validate number field */
400
2
  if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) {
401
0
    zlog_info(
402
0
      "%s ORF Capability entry length error, Cap length %u, num %u",
403
0
      peer->host, hdr->length, num);
404
0
    bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
405
0
        BGP_NOTIFY_OPEN_MALFORMED_ATTR);
406
0
    return -1;
407
0
  }
408
409
14
  for (i = 0; i < num; i++) {
410
12
    type = stream_getc(s);
411
12
    mode = stream_getc(s);
412
413
    /* ORF Mode error check */
414
12
    switch (mode) {
415
0
    case ORF_MODE_BOTH:
416
2
    case ORF_MODE_SEND:
417
4
    case ORF_MODE_RECEIVE:
418
4
      break;
419
8
    default:
420
8
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
421
8
                   type, mode);
422
8
      continue;
423
12
    }
424
    /* ORF Type and afi/safi error checks */
425
    /* capcode versus type */
426
4
    switch (hdr->code) {
427
0
    case CAPABILITY_CODE_ORF:
428
0
      switch (type) {
429
0
      case ORF_TYPE_RESERVED:
430
0
        if (bgp_debug_neighbor_events(peer))
431
0
          zlog_debug(
432
0
            "%s Addr-family %d/%d has reserved ORF type, ignoring",
433
0
            peer->host, afi, safi);
434
0
        break;
435
0
      case ORF_TYPE_PREFIX:
436
0
        break;
437
0
      default:
438
0
        bgp_capability_orf_not_support(
439
0
          peer, pkt_afi, pkt_safi, type, mode);
440
0
        continue;
441
0
      }
442
0
      break;
443
4
    case CAPABILITY_CODE_ORF_OLD:
444
4
      switch (type) {
445
2
      case ORF_TYPE_RESERVED:
446
2
        if (bgp_debug_neighbor_events(peer))
447
0
          zlog_debug(
448
2
            "%s Addr-family %d/%d has reserved ORF type, ignoring",
449
2
            peer->host, afi, safi);
450
2
        break;
451
2
      case ORF_TYPE_PREFIX_OLD:
452
2
        break;
453
0
      default:
454
0
        bgp_capability_orf_not_support(
455
0
          peer, pkt_afi, pkt_safi, type, mode);
456
0
        continue;
457
4
      }
458
4
      break;
459
4
    default:
460
0
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
461
0
                   type, mode);
462
0
      continue;
463
4
    }
464
465
    /* AFI vs SAFI */
466
4
    if (!((afi == AFI_IP && safi == SAFI_UNICAST)
467
4
          || (afi == AFI_IP && safi == SAFI_MULTICAST)
468
4
          || (afi == AFI_IP6 && safi == SAFI_UNICAST))) {
469
0
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
470
0
                   type, mode);
471
0
      continue;
472
0
    }
473
474
4
    if (bgp_debug_neighbor_events(peer))
475
0
      zlog_debug(
476
4
        "%s OPEN has %s ORF capability as %s for afi/safi: %s/%s",
477
4
        peer->host,
478
4
        lookup_msg(orf_type_str, type, NULL),
479
4
        lookup_msg(orf_mode_str, mode, NULL),
480
4
        iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
481
482
4
    if (hdr->code == CAPABILITY_CODE_ORF) {
483
0
      sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
484
0
      rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
485
4
    } else if (hdr->code == CAPABILITY_CODE_ORF_OLD) {
486
4
      sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
487
4
      rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
488
4
    } else {
489
0
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
490
0
                   type, mode);
491
0
      continue;
492
0
    }
493
494
4
    switch (mode) {
495
0
    case ORF_MODE_BOTH:
496
0
      SET_FLAG(peer->af_cap[afi][safi], sm_cap);
497
0
      SET_FLAG(peer->af_cap[afi][safi], rm_cap);
498
0
      break;
499
2
    case ORF_MODE_SEND:
500
2
      SET_FLAG(peer->af_cap[afi][safi], sm_cap);
501
2
      break;
502
2
    case ORF_MODE_RECEIVE:
503
2
      SET_FLAG(peer->af_cap[afi][safi], rm_cap);
504
2
      break;
505
4
    }
506
4
  }
507
2
  return 0;
508
2
}
509
510
static int bgp_capability_restart(struct peer *peer,
511
          struct capability_header *caphdr)
512
17
{
513
17
  struct stream *s = BGP_INPUT(peer);
514
17
  uint16_t restart_flag_time;
515
17
  size_t end = stream_get_getp(s) + caphdr->length;
516
517
  /* Verify length is a multiple of 4 */
518
17
  if ((caphdr->length - 2) % 4) {
519
0
    flog_warn(
520
0
      EC_BGP_CAPABILITY_INVALID_LENGTH,
521
0
      "Restart Cap: Received invalid length %d, non-multiple of 4",
522
0
      caphdr->length);
523
0
    return -1;
524
0
  }
525
526
17
  SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
527
17
  restart_flag_time = stream_getw(s);
528
529
  /* The most significant bit is defined in [RFC4724] as
530
   * the Restart State ("R") bit.
531
   */
532
17
  if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_R_BIT))
533
4
    SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
534
13
  else
535
13
    UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
536
537
  /* The second most significant bit is defined in this
538
   * document as the Graceful Notification ("N") bit.
539
   */
540
17
  if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_N_BIT))
541
10
    SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
542
7
  else
543
7
    UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
544
545
17
  UNSET_FLAG(restart_flag_time, 0xF000);
546
17
  peer->v_gr_restart = restart_flag_time;
547
548
17
  if (bgp_debug_neighbor_events(peer)) {
549
0
    zlog_debug(
550
0
      "%s Peer has%srestarted. Restart Time: %d, N-bit set: %s",
551
0
      peer->host,
552
0
      CHECK_FLAG(peer->cap,
553
0
           PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)
554
0
        ? " "
555
0
        : " not ",
556
0
      peer->v_gr_restart,
557
0
      CHECK_FLAG(peer->cap,
558
0
           PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV)
559
0
        ? "yes"
560
0
        : "no");
561
0
  }
562
563
53
  while (stream_get_getp(s) + 4 <= end) {
564
36
    afi_t afi;
565
36
    safi_t safi;
566
36
    iana_afi_t pkt_afi = stream_getw(s);
567
36
    iana_safi_t pkt_safi = stream_getc(s);
568
36
    uint8_t flag = stream_getc(s);
569
570
    /* Convert AFI, SAFI to internal values, check. */
571
36
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
572
36
      if (bgp_debug_neighbor_events(peer))
573
0
        zlog_debug(
574
36
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Graceful Restart capability for this AFI/SAFI",
575
36
          peer->host, iana_afi2str(pkt_afi),
576
36
          iana_safi2str(pkt_safi));
577
36
    } else if (!peer->afc[afi][safi]) {
578
0
      if (bgp_debug_neighbor_events(peer))
579
0
        zlog_debug(
580
0
          "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Graceful Restart capability",
581
0
          peer->host, iana_afi2str(pkt_afi),
582
0
          iana_safi2str(pkt_safi));
583
0
    } else {
584
0
      if (bgp_debug_neighbor_events(peer))
585
0
        zlog_debug(
586
0
          "%s Address family %s is%spreserved",
587
0
          peer->host, get_afi_safi_str(afi, safi, false),
588
0
          CHECK_FLAG(
589
0
            peer->af_cap[afi][safi],
590
0
            PEER_CAP_RESTART_AF_PRESERVE_RCV)
591
0
            ? " "
592
0
            : " not ");
593
594
0
      SET_FLAG(peer->af_cap[afi][safi],
595
0
         PEER_CAP_RESTART_AF_RCV);
596
0
      if (CHECK_FLAG(flag, GRACEFUL_RESTART_F_BIT))
597
0
        SET_FLAG(peer->af_cap[afi][safi],
598
0
           PEER_CAP_RESTART_AF_PRESERVE_RCV);
599
0
    }
600
36
  }
601
17
  return 0;
602
17
}
603
604
static int bgp_capability_llgr(struct peer *peer,
605
             struct capability_header *caphdr)
606
6
{
607
/*
608
 * +--------------------------------------------------+
609
 * | Address Family Identifier (16 bits)              |
610
 * +--------------------------------------------------+
611
 * | Subsequent Address Family Identifier (8 bits)    |
612
 * +--------------------------------------------------+
613
 * | Flags for Address Family (8 bits)                |
614
 * +--------------------------------------------------+
615
 * | Long-lived Stale Time (24 bits)                  |
616
 * +--------------------------------------------------+
617
 */
618
61
#define BGP_CAP_LLGR_MIN_PACKET_LEN 7
619
6
  struct stream *s = BGP_INPUT(peer);
620
6
  size_t end = stream_get_getp(s) + caphdr->length;
621
622
6
  SET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
623
624
61
  while (stream_get_getp(s) + BGP_CAP_LLGR_MIN_PACKET_LEN <= end) {
625
55
    afi_t afi;
626
55
    safi_t safi;
627
55
    iana_afi_t pkt_afi = stream_getw(s);
628
55
    iana_safi_t pkt_safi = stream_getc(s);
629
55
    uint8_t flags = stream_getc(s);
630
55
    uint32_t stale_time = stream_get3(s);
631
632
55
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
633
55
      if (bgp_debug_neighbor_events(peer))
634
0
        zlog_debug(
635
55
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Long-lived Graceful Restart capability for this AFI/SAFI",
636
55
          peer->host, iana_afi2str(pkt_afi),
637
55
          iana_safi2str(pkt_safi));
638
55
    } else if (!peer->afc[afi][safi]
639
0
         || !CHECK_FLAG(peer->af_cap[afi][safi],
640
0
            PEER_CAP_RESTART_AF_RCV)) {
641
0
      if (bgp_debug_neighbor_events(peer))
642
0
        zlog_debug(
643
0
          "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Long-lived Graceful Restart capability",
644
0
          peer->host, iana_afi2str(pkt_afi),
645
0
          iana_safi2str(pkt_safi));
646
0
    } else {
647
0
      if (bgp_debug_neighbor_events(peer))
648
0
        zlog_debug(
649
0
          "%s Addr-family %s/%s(afi/safi) Long-lived Graceful Restart capability stale time %u sec",
650
0
          peer->host, iana_afi2str(pkt_afi),
651
0
          iana_safi2str(pkt_safi), stale_time);
652
653
0
      peer->llgr[afi][safi].flags = flags;
654
0
      peer->llgr[afi][safi].stale_time =
655
0
        MIN(stale_time, peer->bgp->llgr_stale_time);
656
0
      SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_RCV);
657
0
    }
658
55
  }
659
660
6
  return 0;
661
6
}
662
663
/* Unlike other capability parsing routines, this one returns 0 on error */
664
static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr)
665
190
{
666
190
  SET_FLAG(peer->cap, PEER_CAP_AS4_RCV);
667
668
190
  if (hdr->length != CAPABILITY_CODE_AS4_LEN) {
669
2
    flog_err(EC_BGP_PKT_OPEN,
670
2
       "%s AS4 capability has incorrect data length %d",
671
2
       peer->host, hdr->length);
672
2
    return 0;
673
2
  }
674
675
188
  as_t as4 = stream_getl(BGP_INPUT(peer));
676
677
188
  if (BGP_DEBUG(as4, AS4))
678
0
    zlog_debug(
679
188
      "%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
680
188
      peer->host, as4);
681
188
  return as4;
682
190
}
683
684
static int bgp_capability_ext_message(struct peer *peer,
685
              struct capability_header *hdr)
686
4
{
687
4
  if (hdr->length != CAPABILITY_CODE_EXT_MESSAGE_LEN) {
688
0
    flog_err(
689
0
      EC_BGP_PKT_OPEN,
690
0
      "%s: BGP Extended Message capability has incorrect data length %d",
691
0
      peer->host, hdr->length);
692
0
    return -1;
693
0
  }
694
695
4
  SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV);
696
697
4
  return 0;
698
4
}
699
700
static int bgp_capability_addpath(struct peer *peer,
701
          struct capability_header *hdr)
702
37
{
703
37
  struct stream *s = BGP_INPUT(peer);
704
37
  size_t end = stream_get_getp(s) + hdr->length;
705
706
37
  SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
707
708
  /* Verify length is a multiple of 4 */
709
37
  if (hdr->length % 4) {
710
0
    flog_warn(
711
0
      EC_BGP_CAPABILITY_INVALID_LENGTH,
712
0
      "Add Path: Received invalid length %d, non-multiple of 4",
713
0
      hdr->length);
714
0
    return -1;
715
0
  }
716
717
148
  while (stream_get_getp(s) + 4 <= end) {
718
111
    afi_t afi;
719
111
    safi_t safi;
720
111
    iana_afi_t pkt_afi = stream_getw(s);
721
111
    iana_safi_t pkt_safi = stream_getc(s);
722
111
    uint8_t send_receive = stream_getc(s);
723
724
111
    if (bgp_debug_neighbor_events(peer))
725
0
      zlog_debug(
726
111
        "%s OPEN has %s capability for afi/safi: %s/%s%s%s",
727
111
        peer->host,
728
111
        lookup_msg(capcode_str, hdr->code, NULL),
729
111
        iana_afi2str(pkt_afi), iana_safi2str(pkt_safi),
730
111
        (send_receive & BGP_ADDPATH_RX) ? ", receive"
731
111
                : "",
732
111
        (send_receive & BGP_ADDPATH_TX) ? ", transmit"
733
111
                : "");
734
735
    /* Convert AFI, SAFI to internal values, check. */
736
111
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
737
47
      if (bgp_debug_neighbor_events(peer))
738
0
        zlog_debug(
739
47
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Addpath Attribute for this AFI/SAFI",
740
47
          peer->host, iana_afi2str(pkt_afi),
741
47
          iana_safi2str(pkt_safi));
742
47
      continue;
743
64
    } else if (!peer->afc[afi][safi]) {
744
0
      if (bgp_debug_neighbor_events(peer))
745
0
        zlog_debug(
746
0
          "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the AddPath capability for this AFI/SAFI",
747
0
          peer->host, iana_afi2str(pkt_afi),
748
0
          iana_safi2str(pkt_safi));
749
0
      continue;
750
0
    }
751
752
64
    if (send_receive & BGP_ADDPATH_RX)
753
43
      SET_FLAG(peer->af_cap[afi][safi],
754
64
         PEER_CAP_ADDPATH_AF_RX_RCV);
755
756
64
    if (send_receive & BGP_ADDPATH_TX)
757
20
      SET_FLAG(peer->af_cap[afi][safi],
758
64
         PEER_CAP_ADDPATH_AF_TX_RCV);
759
64
  }
760
761
37
  return 0;
762
37
}
763
764
static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
765
2
{
766
2
  struct stream *s = BGP_INPUT(peer);
767
2
  size_t end = stream_get_getp(s) + hdr->length;
768
769
  /* Verify length is a multiple of 4 */
770
2
  if (hdr->length % 6) {
771
0
    flog_warn(
772
0
      EC_BGP_CAPABILITY_INVALID_LENGTH,
773
0
      "Extended NH: Received invalid length %d, non-multiple of 6",
774
0
      hdr->length);
775
0
    return -1;
776
0
  }
777
778
76
  while (stream_get_getp(s) + 6 <= end) {
779
74
    iana_afi_t pkt_afi = stream_getw(s);
780
74
    afi_t afi;
781
74
    iana_safi_t pkt_safi = stream_getw(s);
782
74
    safi_t safi;
783
74
    iana_afi_t pkt_nh_afi = stream_getw(s);
784
74
    afi_t nh_afi;
785
786
74
    if (bgp_debug_neighbor_events(peer))
787
0
      zlog_debug(
788
74
        "%s Received with afi/safi/next-hop afi: %s/%s/%u",
789
74
        peer->host, iana_afi2str(pkt_afi),
790
74
        iana_safi2str(pkt_safi), pkt_nh_afi);
791
792
    /* Convert AFI, SAFI to internal values, check. */
793
74
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
794
74
      if (bgp_debug_neighbor_events(peer))
795
0
        zlog_debug(
796
74
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the ENHE Attribute for this AFI/SAFI",
797
74
          peer->host, iana_afi2str(pkt_afi),
798
74
          iana_safi2str(pkt_safi));
799
74
      continue;
800
74
    }
801
802
    /* RFC 5549 specifies use of this capability only for IPv4 AFI,
803
     * with
804
     * the Nexthop AFI being IPv6. A future spec may introduce other
805
     * possibilities, so we ignore other values with a log. Also,
806
     * only
807
     * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported
808
     * (and expected).
809
     */
810
0
    nh_afi = afi_iana2int(pkt_nh_afi);
811
812
0
    if (afi != AFI_IP || nh_afi != AFI_IP6
813
0
        || !(safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN
814
0
       || safi == SAFI_LABELED_UNICAST)) {
815
0
      flog_warn(
816
0
        EC_BGP_CAPABILITY_INVALID_DATA,
817
0
        "%s Unexpected afi/safi/next-hop afi: %s/%s/%u in Extended Next-hop capability, ignoring",
818
0
        peer->host, iana_afi2str(pkt_afi),
819
0
        iana_safi2str(pkt_safi), pkt_nh_afi);
820
0
      continue;
821
0
    }
822
823
0
    SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV);
824
825
0
    if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_ADV))
826
0
      SET_FLAG(peer->af_cap[afi][safi],
827
0
         PEER_CAP_ENHE_AF_NEGO);
828
0
  }
829
830
2
  SET_FLAG(peer->cap, PEER_CAP_ENHE_RCV);
831
832
2
  return 0;
833
2
}
834
835
static int bgp_capability_hostname(struct peer *peer,
836
           struct capability_header *hdr)
837
13
{
838
13
  struct stream *s = BGP_INPUT(peer);
839
13
  char str[BGP_MAX_HOSTNAME + 1];
840
13
  size_t end = stream_get_getp(s) + hdr->length;
841
13
  uint8_t len;
842
843
13
  SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
844
845
13
  len = stream_getc(s);
846
13
  if (stream_get_getp(s) + len > end) {
847
0
    flog_warn(
848
0
      EC_BGP_CAPABILITY_INVALID_DATA,
849
0
      "%s: Received malformed hostname capability from peer %s",
850
0
      __func__, peer->host);
851
0
    return -1;
852
0
  }
853
854
13
  if (len > BGP_MAX_HOSTNAME) {
855
0
    stream_get(str, s, BGP_MAX_HOSTNAME);
856
0
    stream_forward_getp(s, len - BGP_MAX_HOSTNAME);
857
0
    len = BGP_MAX_HOSTNAME; /* to set the '\0' below */
858
13
  } else if (len)
859
2
    stream_get(str, s, len);
860
861
13
  if (len) {
862
2
    str[len] = '\0';
863
864
2
    XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
865
2
    XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
866
867
2
    peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
868
2
  }
869
870
13
  if (stream_get_getp(s) + 1 > end) {
871
0
    flog_warn(
872
0
      EC_BGP_CAPABILITY_INVALID_DATA,
873
0
      "%s: Received invalid domain name len (hostname capability) from peer %s",
874
0
      __func__, peer->host);
875
0
    return -1;
876
0
  }
877
878
13
  len = stream_getc(s);
879
13
  if (stream_get_getp(s) + len > end) {
880
0
    flog_warn(
881
0
      EC_BGP_CAPABILITY_INVALID_DATA,
882
0
      "%s: Received runt domain name (hostname capability) from peer %s",
883
0
      __func__, peer->host);
884
0
    return -1;
885
0
  }
886
887
13
  if (len > BGP_MAX_HOSTNAME) {
888
0
    stream_get(str, s, BGP_MAX_HOSTNAME);
889
0
    stream_forward_getp(s, len - BGP_MAX_HOSTNAME);
890
0
    len = BGP_MAX_HOSTNAME; /* to set the '\0' below */
891
13
  } else if (len)
892
5
    stream_get(str, s, len);
893
894
13
  if (len) {
895
5
    str[len] = '\0';
896
897
5
    XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
898
899
5
    peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
900
5
  }
901
902
13
  if (bgp_debug_neighbor_events(peer)) {
903
0
    zlog_debug("%s received hostname %s, domainname %s", peer->host,
904
0
         peer->hostname, peer->domainname);
905
0
  }
906
907
13
  return 0;
908
13
}
909
910
static int bgp_capability_role(struct peer *peer, struct capability_header *hdr)
911
1
{
912
1
  SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
913
1
  if (hdr->length != CAPABILITY_CODE_ROLE_LEN) {
914
0
    flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
915
0
        "Role: Received invalid length %d", hdr->length);
916
0
    return -1;
917
0
  }
918
1
  uint8_t role = stream_getc(BGP_INPUT(peer));
919
920
1
  peer->remote_role = role;
921
1
  return 0;
922
1
}
923
924
static int bgp_capability_software_version(struct peer *peer,
925
             struct capability_header *hdr)
926
5
{
927
5
  struct stream *s = BGP_INPUT(peer);
928
5
  char str[BGP_MAX_SOFT_VERSION + 1];
929
5
  size_t end = stream_get_getp(s) + hdr->length;
930
5
  uint8_t len;
931
932
5
  SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
933
934
5
  len = stream_getc(s);
935
5
  if (stream_get_getp(s) + len > end) {
936
0
    flog_warn(
937
0
      EC_BGP_CAPABILITY_INVALID_DATA,
938
0
      "%s: Received malformed Software Version capability from peer %s",
939
0
      __func__, peer->host);
940
0
    return -1;
941
0
  }
942
943
5
  if (len > BGP_MAX_SOFT_VERSION) {
944
0
    flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
945
0
        "%s: Received Software Version, but the length is too big, truncating, from peer %s",
946
0
        __func__, peer->host);
947
0
    stream_get(str, s, BGP_MAX_SOFT_VERSION);
948
0
    stream_forward_getp(s, len - BGP_MAX_SOFT_VERSION);
949
0
    len = BGP_MAX_SOFT_VERSION;
950
5
  } else if (len) {
951
0
    stream_get(str, s, len);
952
0
  }
953
954
5
  if (len) {
955
0
    str[len] = '\0';
956
957
0
    XFREE(MTYPE_BGP_SOFT_VERSION, peer->soft_version);
958
959
0
    peer->soft_version = XSTRDUP(MTYPE_BGP_SOFT_VERSION, str);
960
961
0
    if (bgp_debug_neighbor_events(peer))
962
0
      zlog_debug("%s sent Software Version: %s", peer->host,
963
0
           peer->soft_version);
964
0
  }
965
966
5
  return 0;
967
5
}
968
969
/**
970
 * Parse given capability.
971
 * XXX: This is reading into a stream, but not using stream API
972
 *
973
 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
974
 *                           capabilities were encountered.
975
 */
976
static int bgp_capability_parse(struct peer *peer, size_t length,
977
        int *mp_capability, uint8_t **error)
978
82
{
979
82
  int ret;
980
82
  struct stream *s = BGP_INPUT(peer);
981
82
  size_t end = stream_get_getp(s) + length;
982
82
  uint16_t restart_flag_time = 0;
983
984
82
  assert(STREAM_READABLE(s) >= length);
985
986
1.92k
  while (stream_get_getp(s) < end) {
987
1.88k
    size_t start;
988
1.88k
    uint8_t *sp = stream_pnt(s);
989
1.88k
    struct capability_header caphdr;
990
991
1.88k
    ret = 0;
992
    /* We need at least capability code and capability length. */
993
1.88k
    if (stream_get_getp(s) + 2 > end) {
994
5
      zlog_info("%s Capability length error (< header)",
995
5
          peer->host);
996
5
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
997
5
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
998
5
      return -1;
999
5
    }
1000
1001
1.87k
    caphdr.code = stream_getc(s);
1002
1.87k
    caphdr.length = stream_getc(s);
1003
1.87k
    start = stream_get_getp(s);
1004
1005
    /* Capability length check sanity check. */
1006
1.87k
    if (start + caphdr.length > end) {
1007
28
      zlog_info("%s Capability length error (< length)",
1008
28
          peer->host);
1009
28
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1010
28
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1011
28
      return -1;
1012
28
    }
1013
1014
1.84k
    if (bgp_debug_neighbor_events(peer))
1015
0
      zlog_debug("%s OPEN has %s capability (%u), length %u",
1016
1.84k
           peer->host,
1017
1.84k
           lookup_msg(capcode_str, caphdr.code, NULL),
1018
1.84k
           caphdr.code, caphdr.length);
1019
1020
    /* Length sanity check, type-specific, for known capabilities */
1021
1.84k
    switch (caphdr.code) {
1022
27
    case CAPABILITY_CODE_MP:
1023
118
    case CAPABILITY_CODE_REFRESH:
1024
151
    case CAPABILITY_CODE_REFRESH_OLD:
1025
154
    case CAPABILITY_CODE_ORF:
1026
156
    case CAPABILITY_CODE_ORF_OLD:
1027
173
    case CAPABILITY_CODE_RESTART:
1028
314
    case CAPABILITY_CODE_AS4:
1029
351
    case CAPABILITY_CODE_ADDPATH:
1030
351
    case CAPABILITY_CODE_DYNAMIC:
1031
359
    case CAPABILITY_CODE_DYNAMIC_OLD:
1032
361
    case CAPABILITY_CODE_ENHE:
1033
374
    case CAPABILITY_CODE_FQDN:
1034
376
    case CAPABILITY_CODE_ENHANCED_RR:
1035
380
    case CAPABILITY_CODE_EXT_MESSAGE:
1036
381
    case CAPABILITY_CODE_ROLE:
1037
386
    case CAPABILITY_CODE_SOFT_VERSION:
1038
      /* Check length. */
1039
386
      if (caphdr.length < cap_minsizes[caphdr.code]) {
1040
3
        zlog_info(
1041
3
          "%s %s Capability length error: got %u, expected at least %u",
1042
3
          peer->host,
1043
3
          lookup_msg(capcode_str, caphdr.code,
1044
3
               NULL),
1045
3
          caphdr.length,
1046
3
          (unsigned)cap_minsizes[caphdr.code]);
1047
3
        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1048
3
            BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1049
3
        return -1;
1050
3
      }
1051
383
      if (caphdr.length
1052
323
          && caphdr.length % cap_modsizes[caphdr.code] != 0) {
1053
0
        zlog_info(
1054
0
          "%s %s Capability length error: got %u, expected a multiple of %u",
1055
0
          peer->host,
1056
0
          lookup_msg(capcode_str, caphdr.code,
1057
0
               NULL),
1058
0
          caphdr.length,
1059
0
          (unsigned)cap_modsizes[caphdr.code]);
1060
0
        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1061
0
            BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1062
0
        return -1;
1063
0
      }
1064
    /* we deliberately ignore unknown codes, see below */
1065
1.84k
    default:
1066
1.84k
      break;
1067
1.84k
    }
1068
1069
1.84k
    switch (caphdr.code) {
1070
25
    case CAPABILITY_CODE_MP: {
1071
25
      *mp_capability = 1;
1072
1073
      /* Ignore capability when override-capability is set. */
1074
25
      if (!CHECK_FLAG(peer->flags,
1075
25
          PEER_FLAG_OVERRIDE_CAPABILITY)) {
1076
        /* Set negotiated value. */
1077
25
        ret = bgp_capability_mp(peer, &caphdr);
1078
1079
        /* Unsupported Capability. */
1080
25
        if (ret < 0) {
1081
          /* Store return data. */
1082
25
          memcpy(*error, sp, caphdr.length + 2);
1083
25
          *error += caphdr.length + 2;
1084
25
        }
1085
25
        ret = 0; /* Don't return error for this */
1086
25
      }
1087
25
    } break;
1088
2
    case CAPABILITY_CODE_ENHANCED_RR:
1089
93
    case CAPABILITY_CODE_REFRESH:
1090
126
    case CAPABILITY_CODE_REFRESH_OLD: {
1091
      /* BGP refresh capability */
1092
126
      if (caphdr.code == CAPABILITY_CODE_ENHANCED_RR)
1093
2
        SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_RCV);
1094
124
      else if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
1095
33
        SET_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV);
1096
91
      else
1097
91
        SET_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV);
1098
126
    } break;
1099
3
    case CAPABILITY_CODE_ORF:
1100
5
    case CAPABILITY_CODE_ORF_OLD:
1101
5
      ret = bgp_capability_orf_entry(peer, &caphdr);
1102
5
      break;
1103
17
    case CAPABILITY_CODE_RESTART:
1104
17
      ret = bgp_capability_restart(peer, &caphdr);
1105
17
      break;
1106
6
    case CAPABILITY_CODE_LLGR:
1107
6
      ret = bgp_capability_llgr(peer, &caphdr);
1108
6
      break;
1109
0
    case CAPABILITY_CODE_DYNAMIC:
1110
8
    case CAPABILITY_CODE_DYNAMIC_OLD:
1111
8
      SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV);
1112
8
      break;
1113
140
    case CAPABILITY_CODE_AS4:
1114
      /* Already handled as a special-case parsing of the
1115
       * capabilities
1116
       * at the beginning of OPEN processing. So we care not a
1117
       * jot
1118
       * for the value really, only error case.
1119
       */
1120
140
      if (!bgp_capability_as4(peer, &caphdr))
1121
2
        ret = -1;
1122
140
      break;
1123
37
    case CAPABILITY_CODE_ADDPATH:
1124
37
      ret = bgp_capability_addpath(peer, &caphdr);
1125
37
      break;
1126
2
    case CAPABILITY_CODE_ENHE:
1127
2
      ret = bgp_capability_enhe(peer, &caphdr);
1128
2
      break;
1129
4
    case CAPABILITY_CODE_EXT_MESSAGE:
1130
4
      ret = bgp_capability_ext_message(peer, &caphdr);
1131
4
      break;
1132
13
    case CAPABILITY_CODE_FQDN:
1133
13
      ret = bgp_capability_hostname(peer, &caphdr);
1134
13
      break;
1135
1
    case CAPABILITY_CODE_ROLE:
1136
1
      ret = bgp_capability_role(peer, &caphdr);
1137
1
      break;
1138
5
    case CAPABILITY_CODE_SOFT_VERSION:
1139
5
      ret = bgp_capability_software_version(peer, &caphdr);
1140
5
      break;
1141
1.45k
    default:
1142
1.45k
      if (caphdr.code > 128) {
1143
        /* We don't send Notification for unknown vendor
1144
           specific
1145
           capabilities.  It seems reasonable for now...
1146
           */
1147
121
        flog_warn(EC_BGP_CAPABILITY_VENDOR,
1148
121
            "%s Vendor specific capability %d",
1149
121
            peer->host, caphdr.code);
1150
1.33k
      } else {
1151
1.33k
        flog_warn(
1152
1.33k
          EC_BGP_CAPABILITY_UNKNOWN,
1153
1.33k
          "%s unrecognized capability code: %d - ignored",
1154
1.33k
          peer->host, caphdr.code);
1155
1.33k
        memcpy(*error, sp, caphdr.length + 2);
1156
1.33k
        *error += caphdr.length + 2;
1157
1.33k
      }
1158
1.84k
    }
1159
1160
1.84k
    if (ret < 0) {
1161
2
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1162
2
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1163
2
      return -1;
1164
2
    }
1165
1.84k
    if (stream_get_getp(s) != (start + caphdr.length)) {
1166
452
      if (stream_get_getp(s) > (start + caphdr.length))
1167
0
        flog_warn(
1168
452
          EC_BGP_CAPABILITY_INVALID_LENGTH,
1169
452
          "%s Cap-parser for %s read past cap-length, %u!",
1170
452
          peer->host,
1171
452
          lookup_msg(capcode_str, caphdr.code,
1172
452
               NULL),
1173
452
          caphdr.length);
1174
452
      stream_set_getp(s, start + caphdr.length);
1175
452
    }
1176
1177
1.84k
    if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
1178
1.52k
      UNSET_FLAG(restart_flag_time, 0xF000);
1179
1.52k
      peer->v_gr_restart = restart_flag_time;
1180
1.52k
    }
1181
1.84k
  }
1182
44
  return 0;
1183
82
}
1184
1185
static bool strict_capability_same(struct peer *peer)
1186
0
{
1187
0
  int i, j;
1188
1189
0
  for (i = AFI_IP; i < AFI_MAX; i++)
1190
0
    for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
1191
0
      if (peer->afc[i][j] != peer->afc_nego[i][j])
1192
0
        return false;
1193
0
  return true;
1194
0
}
1195
1196
1197
static bool bgp_role_violation(struct peer *peer)
1198
5
{
1199
5
  uint8_t local_role = peer->local_role;
1200
5
  uint8_t remote_role = peer->remote_role;
1201
1202
5
  if (local_role != ROLE_UNDEFINED && remote_role != ROLE_UNDEFINED &&
1203
0
      !((local_role == ROLE_PEER && remote_role == ROLE_PEER) ||
1204
0
        (local_role == ROLE_PROVIDER && remote_role == ROLE_CUSTOMER) ||
1205
0
        (local_role == ROLE_CUSTOMER && remote_role == ROLE_PROVIDER) ||
1206
0
        (local_role == ROLE_RS_SERVER && remote_role == ROLE_RS_CLIENT) ||
1207
0
        (local_role == ROLE_RS_CLIENT &&
1208
0
         remote_role == ROLE_RS_SERVER))) {
1209
0
    bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1210
0
        BGP_NOTIFY_OPEN_ROLE_MISMATCH);
1211
0
    return true;
1212
0
  }
1213
5
  if (remote_role == ROLE_UNDEFINED &&
1214
4
      CHECK_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE)) {
1215
0
    const char *err_msg =
1216
0
      "Strict mode. Please set the role on your side.";
1217
0
    bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
1218
0
            BGP_NOTIFY_OPEN_ROLE_MISMATCH,
1219
0
            (uint8_t *)err_msg, strlen(err_msg));
1220
0
    return true;
1221
0
  }
1222
5
  return false;
1223
5
}
1224
1225
1226
/* peek into option, stores ASN to *as4 if the AS4 capability was found.
1227
 * Returns  0 if no as4 found, as4cap value otherwise.
1228
 */
1229
as_t peek_for_as4_capability(struct peer *peer, uint16_t length)
1230
68
{
1231
68
  struct stream *s = BGP_INPUT(peer);
1232
68
  size_t orig_getp = stream_get_getp(s);
1233
68
  size_t end = orig_getp + length;
1234
68
  as_t as4 = 0;
1235
1236
68
  if (BGP_DEBUG(as4, AS4))
1237
0
    zlog_debug(
1238
68
      "%s [AS4] rcv OPEN w/ OPTION parameter len: %u, peeking for as4",
1239
68
      peer->host, length);
1240
  /* the error cases we DONT handle, we ONLY try to read as4 out of
1241
   * correctly formatted options.
1242
   */
1243
278
  while (stream_get_getp(s) < end) {
1244
277
    uint8_t opt_type;
1245
277
    uint16_t opt_length;
1246
1247
    /* Ensure we can read the option type */
1248
277
    if (stream_get_getp(s) + 1 > end)
1249
0
      goto end;
1250
1251
    /* Fetch the option type */
1252
277
    opt_type = stream_getc(s);
1253
1254
    /*
1255
     * Check the length and fetch the opt_length
1256
     * If the peer is BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
1257
     * then we do a getw which is 2 bytes.  So we need to
1258
     * ensure that we can read that as well
1259
     */
1260
277
    if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
1261
277
      if (stream_get_getp(s) + 2 > end)
1262
3
        goto end;
1263
1264
274
      opt_length = stream_getw(s);
1265
274
    } else {
1266
0
      if (stream_get_getp(s) + 1 > end)
1267
0
        goto end;
1268
1269
0
      opt_length = stream_getc(s);
1270
0
    }
1271
1272
    /* Option length check. */
1273
274
    if (stream_get_getp(s) + opt_length > end)
1274
11
      goto end;
1275
1276
263
    if (opt_type == BGP_OPEN_OPT_CAP) {
1277
62
      unsigned long capd_start = stream_get_getp(s);
1278
62
      unsigned long capd_end = capd_start + opt_length;
1279
1280
62
      assert(capd_end <= end);
1281
1282
188
      while (stream_get_getp(s) < capd_end) {
1283
179
        struct capability_header hdr;
1284
1285
179
        if (stream_get_getp(s) + 2 > capd_end)
1286
1
          goto end;
1287
1288
178
        hdr.code = stream_getc(s);
1289
178
        hdr.length = stream_getc(s);
1290
1291
178
        if ((stream_get_getp(s) + hdr.length)
1292
178
            > capd_end)
1293
2
          goto end;
1294
1295
176
        if (hdr.code == CAPABILITY_CODE_AS4) {
1296
50
          if (BGP_DEBUG(as4, AS4))
1297
0
            zlog_debug(
1298
50
              "[AS4] found AS4 capability, about to parse");
1299
50
          as4 = bgp_capability_as4(peer, &hdr);
1300
1301
50
          goto end;
1302
50
        }
1303
126
        stream_forward_getp(s, hdr.length);
1304
126
      }
1305
62
    }
1306
263
  }
1307
1308
68
end:
1309
68
  stream_set_getp(s, orig_getp);
1310
68
  return as4;
1311
68
}
1312
1313
/**
1314
 * Parse open option.
1315
 *
1316
 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
1317
 */
1318
int bgp_open_option_parse(struct peer *peer, uint16_t length,
1319
        int *mp_capability)
1320
48
{
1321
48
  int ret = 0;
1322
48
  uint8_t *error;
1323
48
  uint8_t error_data[BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE];
1324
48
  struct stream *s = BGP_INPUT(peer);
1325
48
  size_t end = stream_get_getp(s) + length;
1326
1327
48
  error = error_data;
1328
1329
48
  if (bgp_debug_neighbor_events(peer))
1330
0
    zlog_debug("%s rcv OPEN w/ OPTION parameter len: %u",
1331
48
         peer->host, length);
1332
1333
  /* Unset any previously received GR capability. */
1334
48
  UNSET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
1335
1336
92
  while (stream_get_getp(s) < end) {
1337
87
    uint8_t opt_type;
1338
87
    uint16_t opt_length;
1339
1340
    /*
1341
     * Check that we can read the opt_type and fetch it
1342
     */
1343
87
    if (STREAM_READABLE(s) < 1) {
1344
0
      zlog_info("%s Option length error", peer->host);
1345
0
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1346
0
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1347
0
      return -1;
1348
0
    }
1349
87
    opt_type = stream_getc(s);
1350
1351
    /*
1352
     * Check the length of the stream to ensure that
1353
     * FRR can properly read the opt_length. Then read it
1354
     */
1355
87
    if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
1356
87
      if (STREAM_READABLE(s) < 2) {
1357
0
        zlog_info("%s Option length error", peer->host);
1358
0
        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1359
0
            BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1360
0
        return -1;
1361
0
      }
1362
1363
87
      opt_length = stream_getw(s);
1364
87
    } else {
1365
0
      if (STREAM_READABLE(s) < 1) {
1366
0
        zlog_info("%s Option length error", peer->host);
1367
0
        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1368
0
            BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1369
0
        return -1;
1370
0
      }
1371
1372
0
      opt_length = stream_getc(s);
1373
0
    }
1374
1375
    /* Option length check. */
1376
87
    if (STREAM_READABLE(s) < opt_length) {
1377
2
      zlog_info("%s Option length error (%d)", peer->host,
1378
2
          opt_length);
1379
2
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1380
2
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1381
2
      return -1;
1382
2
    }
1383
1384
85
    if (bgp_debug_neighbor_events(peer))
1385
0
      zlog_debug(
1386
85
        "%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
1387
85
        peer->host, opt_type,
1388
85
        opt_type == BGP_OPEN_OPT_CAP ? "Capability"
1389
85
                   : "Unknown",
1390
85
        opt_length);
1391
1392
85
    switch (opt_type) {
1393
82
    case BGP_OPEN_OPT_CAP:
1394
82
      ret = bgp_capability_parse(peer, opt_length,
1395
82
               mp_capability, &error);
1396
82
      break;
1397
3
    default:
1398
3
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1399
3
          BGP_NOTIFY_OPEN_UNSUP_PARAM);
1400
3
      ret = -1;
1401
3
      break;
1402
85
    }
1403
1404
    /* Parse error.  To accumulate all unsupported capability codes,
1405
       bgp_capability_parse does not return -1 when encounter
1406
       unsupported capability code.  To detect that, please check
1407
       error and erro_data pointer, like below.  */
1408
85
    if (ret < 0)
1409
41
      return -1;
1410
85
  }
1411
1412
  /* All OPEN option is parsed.  Check capability when strict compare
1413
     flag is enabled.*/
1414
5
  if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
1415
    /* If Unsupported Capability exists. */
1416
0
    if (error != error_data) {
1417
0
      bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
1418
0
              BGP_NOTIFY_OPEN_UNSUP_CAPBL,
1419
0
              error_data,
1420
0
              error - error_data);
1421
0
      return -1;
1422
0
    }
1423
1424
    /* Check local capability does not negotiated with remote
1425
       peer. */
1426
0
    if (!strict_capability_same(peer)) {
1427
0
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1428
0
          BGP_NOTIFY_OPEN_UNSUP_CAPBL);
1429
0
      return -1;
1430
0
    }
1431
0
  }
1432
1433
  /* Extended Message Support */
1434
5
  peer->max_packet_size =
1435
5
    (CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV)
1436
5
     && CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV))
1437
5
      ? BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE
1438
5
      : BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
1439
1440
  /* Check that roles are corresponding to each other */
1441
5
  if (bgp_role_violation(peer))
1442
0
    return -1;
1443
1444
  /* Check there are no common AFI/SAFIs and send Unsupported Capability
1445
     error. */
1446
5
  if (*mp_capability
1447
2
      && !CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) {
1448
2
    if (!peer->afc_nego[AFI_IP][SAFI_UNICAST]
1449
1
        && !peer->afc_nego[AFI_IP][SAFI_MULTICAST]
1450
1
        && !peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
1451
1
        && !peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
1452
1
        && !peer->afc_nego[AFI_IP][SAFI_ENCAP]
1453
1
        && !peer->afc_nego[AFI_IP][SAFI_FLOWSPEC]
1454
1
        && !peer->afc_nego[AFI_IP6][SAFI_UNICAST]
1455
1
        && !peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
1456
1
        && !peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
1457
1
        && !peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
1458
1
        && !peer->afc_nego[AFI_IP6][SAFI_ENCAP]
1459
1
        && !peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC]
1460
1
        && !peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) {
1461
1
      flog_err(EC_BGP_PKT_OPEN,
1462
1
         "%s [Error] Configured AFI/SAFIs do not overlap with received MP capabilities",
1463
1
         peer->host);
1464
1465
1
      if (error != error_data)
1466
1
        bgp_notify_send_with_data(
1467
1
          peer, BGP_NOTIFY_OPEN_ERR,
1468
1
          BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data,
1469
1
          error - error_data);
1470
0
      else
1471
0
        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1472
0
            BGP_NOTIFY_OPEN_UNSUP_CAPBL);
1473
1
      return -1;
1474
1
    }
1475
2
  }
1476
4
  return 0;
1477
5
}
1478
1479
static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
1480
            afi_t afi, safi_t safi, uint8_t code,
1481
            bool ext_opt_params)
1482
0
{
1483
0
  uint16_t cap_len;
1484
0
  uint8_t orf_len;
1485
0
  unsigned long capp;
1486
0
  unsigned long orfp;
1487
0
  unsigned long numberp;
1488
0
  int number_of_orfs = 0;
1489
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
1490
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
1491
1492
  /* Convert AFI, SAFI to values for packet. */
1493
0
  bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
1494
1495
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1496
0
  capp = stream_get_endp(s); /* Set Capability Len Pointer */
1497
0
  ext_opt_params ? stream_putw(s, 0)
1498
0
           : stream_putc(s, 0); /* Capability Length */
1499
0
  stream_putc(s, code);      /* Capability Code */
1500
0
  orfp = stream_get_endp(s); /* Set ORF Len Pointer */
1501
0
  stream_putc(s, 0);   /* ORF Length */
1502
0
  stream_putw(s, pkt_afi);
1503
0
  stream_putc(s, 0);
1504
0
  stream_putc(s, pkt_safi);
1505
0
  numberp = stream_get_endp(s); /* Set Number Pointer */
1506
0
  stream_putc(s, 0);      /* Number of ORFs */
1507
1508
  /* Address Prefix ORF */
1509
0
  if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1510
0
      || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) {
1511
0
    stream_putc(s, (code == CAPABILITY_CODE_ORF
1512
0
          ? ORF_TYPE_PREFIX
1513
0
          : ORF_TYPE_PREFIX_OLD));
1514
1515
0
    if (CHECK_FLAG(peer->af_flags[afi][safi],
1516
0
             PEER_FLAG_ORF_PREFIX_SM)
1517
0
        && CHECK_FLAG(peer->af_flags[afi][safi],
1518
0
          PEER_FLAG_ORF_PREFIX_RM)) {
1519
0
      SET_FLAG(peer->af_cap[afi][safi],
1520
0
         PEER_CAP_ORF_PREFIX_SM_ADV);
1521
0
      SET_FLAG(peer->af_cap[afi][safi],
1522
0
         PEER_CAP_ORF_PREFIX_RM_ADV);
1523
0
      stream_putc(s, ORF_MODE_BOTH);
1524
0
    } else if (CHECK_FLAG(peer->af_flags[afi][safi],
1525
0
              PEER_FLAG_ORF_PREFIX_SM)) {
1526
0
      SET_FLAG(peer->af_cap[afi][safi],
1527
0
         PEER_CAP_ORF_PREFIX_SM_ADV);
1528
0
      stream_putc(s, ORF_MODE_SEND);
1529
0
    } else {
1530
0
      SET_FLAG(peer->af_cap[afi][safi],
1531
0
         PEER_CAP_ORF_PREFIX_RM_ADV);
1532
0
      stream_putc(s, ORF_MODE_RECEIVE);
1533
0
    }
1534
0
    number_of_orfs++;
1535
0
  }
1536
1537
  /* Total Number of ORFs. */
1538
0
  stream_putc_at(s, numberp, number_of_orfs);
1539
1540
  /* Total ORF Len. */
1541
0
  orf_len = stream_get_endp(s) - orfp - 1;
1542
0
  stream_putc_at(s, orfp, orf_len);
1543
1544
  /* Total Capability Len. */
1545
0
  cap_len = stream_get_endp(s) - capp - 1;
1546
0
  ext_opt_params ? stream_putw_at(s, capp, cap_len)
1547
0
           : stream_putc_at(s, capp, cap_len);
1548
0
}
1549
1550
static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
1551
          bool ext_opt_params)
1552
0
{
1553
0
  int len;
1554
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
1555
0
  afi_t afi;
1556
0
  safi_t safi;
1557
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
1558
0
  uint32_t restart_time;
1559
0
  unsigned long capp = 0;
1560
0
  unsigned long rcapp = 0;
1561
1562
0
  if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
1563
0
      && !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER))
1564
0
    return;
1565
1566
0
  if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1567
0
    zlog_debug("[BGP_GR] Sending helper Capability for Peer :%s :",
1568
0
         peer->host);
1569
1570
0
  SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
1571
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1572
0
  capp = stream_get_endp(s); /* Set Capability Len Pointer */
1573
0
  ext_opt_params ? stream_putw(s, 0)
1574
0
           : stream_putc(s, 0); /* Capability Length */
1575
0
  stream_putc(s, CAPABILITY_CODE_RESTART);
1576
  /* Set Restart Capability Len Pointer */
1577
0
  rcapp = stream_get_endp(s);
1578
0
  stream_putc(s, 0);
1579
0
  restart_time = peer->bgp->restart_time;
1580
0
  if (peer->bgp->t_startup) {
1581
0
    SET_FLAG(restart_time, GRACEFUL_RESTART_R_BIT);
1582
0
    SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
1583
0
    if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1584
0
      zlog_debug("[BGP_GR] Sending R-Bit for peer: %s",
1585
0
           peer->host);
1586
0
  }
1587
1588
0
  if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION)) {
1589
0
    SET_FLAG(restart_time, GRACEFUL_RESTART_N_BIT);
1590
0
    SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV);
1591
0
    if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1592
0
      zlog_debug("[BGP_GR] Sending N-Bit for peer: %s",
1593
0
           peer->host);
1594
0
  }
1595
1596
0
  stream_putw(s, restart_time);
1597
1598
  /* Send address-family specific graceful-restart capability
1599
   * only when GR config is present
1600
   */
1601
0
  if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)) {
1602
0
    if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)
1603
0
        && BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1604
0
      zlog_debug("[BGP_GR] F bit Set");
1605
1606
0
    FOREACH_AFI_SAFI (afi, safi) {
1607
0
      if (!peer->afc[afi][safi])
1608
0
        continue;
1609
1610
0
      if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
1611
0
        zlog_debug(
1612
0
          "[BGP_GR] Sending GR Capability for AFI :%d :, SAFI :%d:",
1613
0
          afi, safi);
1614
1615
      /* Convert AFI, SAFI to values for
1616
       * packet.
1617
       */
1618
0
      bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
1619
0
              &pkt_safi);
1620
0
      stream_putw(s, pkt_afi);
1621
0
      stream_putc(s, pkt_safi);
1622
0
      if (CHECK_FLAG(peer->bgp->flags,
1623
0
               BGP_FLAG_GR_PRESERVE_FWD))
1624
0
        stream_putc(s, GRACEFUL_RESTART_F_BIT);
1625
0
      else
1626
0
        stream_putc(s, 0);
1627
0
    }
1628
0
  }
1629
1630
  /* Total Graceful restart capability Len. */
1631
0
  len = stream_get_endp(s) - rcapp - 1;
1632
0
  stream_putc_at(s, rcapp, len);
1633
1634
  /* Total Capability Len. */
1635
0
  len = stream_get_endp(s) - capp - 1;
1636
0
  ext_opt_params ? stream_putw_at(s, capp, len - 1)
1637
0
           : stream_putc_at(s, capp, len);
1638
0
}
1639
1640
static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
1641
            bool ext_opt_params)
1642
0
{
1643
0
  int len;
1644
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
1645
0
  afi_t afi;
1646
0
  safi_t safi;
1647
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
1648
0
  unsigned long capp = 0;
1649
0
  unsigned long rcapp = 0;
1650
1651
0
  if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV))
1652
0
    return;
1653
1654
0
  SET_FLAG(peer->cap, PEER_CAP_LLGR_ADV);
1655
1656
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1657
0
  capp = stream_get_endp(s); /* Set Capability Len Pointer */
1658
0
  ext_opt_params ? stream_putw(s, 0)
1659
0
           : stream_putc(s, 0); /* Capability Length */
1660
0
  stream_putc(s, CAPABILITY_CODE_LLGR);
1661
1662
0
  rcapp = stream_get_endp(s);
1663
0
  stream_putc(s, 0);
1664
1665
0
  FOREACH_AFI_SAFI (afi, safi) {
1666
0
    if (!peer->afc[afi][safi])
1667
0
      continue;
1668
1669
0
    bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
1670
1671
0
    stream_putw(s, pkt_afi);
1672
0
    stream_putc(s, pkt_safi);
1673
0
    stream_putc(s, LLGR_F_BIT);
1674
0
    stream_put3(s, peer->bgp->llgr_stale_time);
1675
1676
0
    SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_ADV);
1677
0
  }
1678
1679
  /* Total Long-lived Graceful Restart capability Len. */
1680
0
  len = stream_get_endp(s) - rcapp - 1;
1681
0
  stream_putc_at(s, rcapp, len);
1682
1683
  /* Total Capability Len. */
1684
0
  len = stream_get_endp(s) - capp - 1;
1685
0
  ext_opt_params ? stream_putw_at(s, capp, len - 1)
1686
0
           : stream_putc_at(s, capp, len);
1687
0
}
1688
1689
/* Fill in capability open option to the packet. */
1690
uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
1691
           bool ext_opt_params)
1692
0
{
1693
0
  uint16_t len;
1694
0
  unsigned long cp, capp, rcapp, eopl = 0;
1695
0
  iana_afi_t pkt_afi = IANA_AFI_IPV4;
1696
0
  afi_t afi;
1697
0
  safi_t safi;
1698
0
  iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
1699
0
  as_t local_as;
1700
0
  uint8_t afi_safi_count = 0;
1701
0
  bool adv_addpath_tx = false;
1702
1703
  /* Non-Ext OP Len. */
1704
0
  cp = stream_get_endp(s);
1705
0
  stream_putc(s, 0);
1706
1707
0
  if (ext_opt_params) {
1708
    /* Non-Ext OP Len. */
1709
0
    stream_putc_at(s, cp, BGP_OPEN_NON_EXT_OPT_LEN);
1710
1711
    /* Non-Ext OP Type */
1712
0
    stream_putc(s, BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH);
1713
1714
    /* Extended Opt. Parm. Length */
1715
0
    eopl = stream_get_endp(s);
1716
0
    stream_putw(s, 0);
1717
0
  }
1718
1719
  /* Do not send capability. */
1720
0
  if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
1721
0
      || CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY))
1722
0
    return 0;
1723
1724
  /* MP capability for configured AFI, SAFI */
1725
0
  FOREACH_AFI_SAFI (afi, safi) {
1726
0
    if (peer->afc[afi][safi]) {
1727
      /* Convert AFI, SAFI to values for packet. */
1728
0
      bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
1729
0
              &pkt_safi);
1730
1731
0
      peer->afc_adv[afi][safi] = 1;
1732
0
      stream_putc(s, BGP_OPEN_OPT_CAP);
1733
0
      ext_opt_params
1734
0
        ? stream_putw(s, CAPABILITY_CODE_MP_LEN + 2)
1735
0
        : stream_putc(s, CAPABILITY_CODE_MP_LEN + 2);
1736
0
      stream_putc(s, CAPABILITY_CODE_MP);
1737
0
      stream_putc(s, CAPABILITY_CODE_MP_LEN);
1738
0
      stream_putw(s, pkt_afi);
1739
0
      stream_putc(s, 0);
1740
0
      stream_putc(s, pkt_safi);
1741
1742
      /* Extended nexthop capability - currently
1743
       * supporting RFC-5549 for
1744
       * Link-Local peering only
1745
       */
1746
0
      if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
1747
0
          && peer->su.sa.sa_family == AF_INET6
1748
0
          && afi == AFI_IP
1749
0
          && (safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN
1750
0
        || safi == SAFI_LABELED_UNICAST)) {
1751
        /* RFC 5549 Extended Next Hop Encoding
1752
         */
1753
0
        SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV);
1754
0
        stream_putc(s, BGP_OPEN_OPT_CAP);
1755
0
        ext_opt_params
1756
0
          ? stream_putw(s,
1757
0
                  CAPABILITY_CODE_ENHE_LEN
1758
0
                    + 2)
1759
0
          : stream_putc(s,
1760
0
                  CAPABILITY_CODE_ENHE_LEN
1761
0
                    + 2);
1762
0
        stream_putc(s, CAPABILITY_CODE_ENHE);
1763
0
        stream_putc(s, CAPABILITY_CODE_ENHE_LEN);
1764
1765
0
        SET_FLAG(peer->af_cap[AFI_IP][safi],
1766
0
           PEER_CAP_ENHE_AF_ADV);
1767
0
        stream_putw(s, pkt_afi);
1768
0
        stream_putw(s, pkt_safi);
1769
0
        stream_putw(s, afi_int2iana(AFI_IP6));
1770
1771
0
        if (CHECK_FLAG(peer->af_cap[afi][safi],
1772
0
                 PEER_CAP_ENHE_AF_RCV))
1773
0
          SET_FLAG(peer->af_cap[afi][safi],
1774
0
             PEER_CAP_ENHE_AF_NEGO);
1775
0
      }
1776
0
    }
1777
0
  }
1778
1779
  /* Route refresh. */
1780
0
  SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV);
1781
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1782
0
  ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
1783
0
           : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
1784
0
  stream_putc(s, CAPABILITY_CODE_REFRESH_OLD);
1785
0
  stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
1786
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1787
0
  ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
1788
0
           : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
1789
0
  stream_putc(s, CAPABILITY_CODE_REFRESH);
1790
0
  stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
1791
1792
  /* Enhanced Route Refresh. */
1793
0
  SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_ADV);
1794
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1795
0
  ext_opt_params ? stream_putw(s, CAPABILITY_CODE_ENHANCED_LEN + 2)
1796
0
           : stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN + 2);
1797
0
  stream_putc(s, CAPABILITY_CODE_ENHANCED_RR);
1798
0
  stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN);
1799
1800
  /* AS4 */
1801
0
  SET_FLAG(peer->cap, PEER_CAP_AS4_ADV);
1802
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1803
0
  ext_opt_params ? stream_putw(s, CAPABILITY_CODE_AS4_LEN + 2)
1804
0
           : stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2);
1805
0
  stream_putc(s, CAPABILITY_CODE_AS4);
1806
0
  stream_putc(s, CAPABILITY_CODE_AS4_LEN);
1807
0
  if (peer->change_local_as)
1808
0
    local_as = peer->change_local_as;
1809
0
  else
1810
0
    local_as = peer->local_as;
1811
0
  stream_putl(s, local_as);
1812
1813
  /* Extended Message Support */
1814
0
  SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV);
1815
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1816
0
  ext_opt_params ? stream_putw(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2)
1817
0
           : stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
1818
0
  stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE);
1819
0
  stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN);
1820
1821
  /* Role*/
1822
0
  if (peer->local_role != ROLE_UNDEFINED) {
1823
0
    SET_FLAG(peer->cap, PEER_CAP_ROLE_ADV);
1824
0
    stream_putc(s, BGP_OPEN_OPT_CAP);
1825
0
    stream_putc(s, CAPABILITY_CODE_ROLE_LEN + 2);
1826
0
    stream_putc(s, CAPABILITY_CODE_ROLE);
1827
0
    stream_putc(s, CAPABILITY_CODE_ROLE_LEN);
1828
0
    stream_putc(s, peer->local_role);
1829
0
  }
1830
1831
  /* AddPath */
1832
0
  FOREACH_AFI_SAFI (afi, safi) {
1833
0
    if (peer->afc[afi][safi]) {
1834
0
      afi_safi_count++;
1835
1836
      /* Only advertise addpath TX if a feature that
1837
       * will use it is
1838
       * configured */
1839
0
      if (peer->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
1840
0
        adv_addpath_tx = true;
1841
1842
      /* If we have enabled labeled unicast, we MUST check
1843
       * against unicast SAFI because addpath IDs are
1844
       * allocated under unicast SAFI, the same as the RIB
1845
       * is managed in unicast SAFI.
1846
       */
1847
0
      if (safi == SAFI_LABELED_UNICAST)
1848
0
        if (peer->addpath_type[afi][SAFI_UNICAST] !=
1849
0
            BGP_ADDPATH_NONE)
1850
0
          adv_addpath_tx = true;
1851
0
    }
1852
0
  }
1853
1854
0
  SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV);
1855
0
  stream_putc(s, BGP_OPEN_OPT_CAP);
1856
0
  ext_opt_params
1857
0
    ? stream_putw(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
1858
0
           + 2)
1859
0
    : stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
1860
0
           + 2);
1861
0
  stream_putc(s, CAPABILITY_CODE_ADDPATH);
1862
0
  stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count);
1863
1864
0
  FOREACH_AFI_SAFI (afi, safi) {
1865
0
    if (peer->afc[afi][safi]) {
1866
0
      bool adv_addpath_rx =
1867
0
        !CHECK_FLAG(peer->af_flags[afi][safi],
1868
0
              PEER_FLAG_DISABLE_ADDPATH_RX);
1869
0
      uint8_t flags = 0;
1870
1871
      /* Convert AFI, SAFI to values for packet. */
1872
0
      bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
1873
0
              &pkt_safi);
1874
1875
0
      stream_putw(s, pkt_afi);
1876
0
      stream_putc(s, pkt_safi);
1877
1878
0
      if (adv_addpath_rx) {
1879
0
        SET_FLAG(flags, BGP_ADDPATH_RX);
1880
0
        SET_FLAG(peer->af_cap[afi][safi],
1881
0
           PEER_CAP_ADDPATH_AF_RX_ADV);
1882
0
      } else {
1883
0
        UNSET_FLAG(peer->af_cap[afi][safi],
1884
0
             PEER_CAP_ADDPATH_AF_RX_ADV);
1885
0
      }
1886
1887
0
      if (adv_addpath_tx) {
1888
0
        SET_FLAG(flags, BGP_ADDPATH_TX);
1889
0
        SET_FLAG(peer->af_cap[afi][safi],
1890
0
           PEER_CAP_ADDPATH_AF_TX_ADV);
1891
0
        if (safi == SAFI_LABELED_UNICAST)
1892
0
          SET_FLAG(
1893
0
            peer->af_cap[afi][SAFI_UNICAST],
1894
0
            PEER_CAP_ADDPATH_AF_TX_ADV);
1895
0
      } else {
1896
0
        UNSET_FLAG(peer->af_cap[afi][safi],
1897
0
             PEER_CAP_ADDPATH_AF_TX_ADV);
1898
0
      }
1899
1900
0
      stream_putc(s, flags);
1901
0
    }
1902
0
  }
1903
1904
  /* ORF capability. */
1905
0
  FOREACH_AFI_SAFI (afi, safi) {
1906
0
    if (CHECK_FLAG(peer->af_flags[afi][safi],
1907
0
             PEER_FLAG_ORF_PREFIX_SM)
1908
0
        || CHECK_FLAG(peer->af_flags[afi][safi],
1909
0
          PEER_FLAG_ORF_PREFIX_RM)) {
1910
0
      bgp_open_capability_orf(s, peer, afi, safi,
1911
0
            CAPABILITY_CODE_ORF_OLD,
1912
0
            ext_opt_params);
1913
0
      bgp_open_capability_orf(s, peer, afi, safi,
1914
0
            CAPABILITY_CODE_ORF,
1915
0
            ext_opt_params);
1916
0
    }
1917
0
  }
1918
1919
  /* Dynamic capability. */
1920
0
  if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
1921
0
    SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
1922
0
    stream_putc(s, BGP_OPEN_OPT_CAP);
1923
0
    ext_opt_params
1924
0
      ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
1925
0
      : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1926
0
    stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD);
1927
0
    stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
1928
0
    stream_putc(s, BGP_OPEN_OPT_CAP);
1929
0
    ext_opt_params
1930
0
      ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
1931
0
      : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1932
0
    stream_putc(s, CAPABILITY_CODE_DYNAMIC);
1933
0
    stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
1934
0
  }
1935
1936
  /* Hostname capability */
1937
0
  if (cmd_hostname_get()) {
1938
0
    SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
1939
0
    stream_putc(s, BGP_OPEN_OPT_CAP);
1940
0
    rcapp = stream_get_endp(s); /* Ptr to length placeholder */
1941
0
    ext_opt_params ? stream_putw(s, 0)
1942
0
             : stream_putc(s, 0); /* Capability Length */
1943
0
    stream_putc(s, CAPABILITY_CODE_FQDN);
1944
0
    capp = stream_get_endp(s);
1945
0
    stream_putc(s, 0); /* dummy len for now */
1946
0
    len = strlen(cmd_hostname_get());
1947
0
    if (len > BGP_MAX_HOSTNAME)
1948
0
      len = BGP_MAX_HOSTNAME;
1949
1950
0
    stream_putc(s, len);
1951
0
    stream_put(s, cmd_hostname_get(), len);
1952
0
    if (cmd_domainname_get()) {
1953
0
      len = strlen(cmd_domainname_get());
1954
0
      if (len > BGP_MAX_HOSTNAME)
1955
0
        len = BGP_MAX_HOSTNAME;
1956
1957
0
      stream_putc(s, len);
1958
0
      stream_put(s, cmd_domainname_get(), len);
1959
0
    } else
1960
0
      stream_putc(s, 0); /* 0 length */
1961
1962
    /* Set the lengths straight */
1963
0
    len = stream_get_endp(s) - rcapp - 1;
1964
0
    ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
1965
0
             : stream_putc_at(s, rcapp, len);
1966
1967
0
    len = stream_get_endp(s) - capp - 1;
1968
0
    stream_putc_at(s, capp, len);
1969
1970
0
    if (bgp_debug_neighbor_events(peer))
1971
0
      zlog_debug(
1972
0
        "%s Sending hostname cap with hn = %s, dn = %s",
1973
0
        peer->host, cmd_hostname_get(),
1974
0
        cmd_domainname_get());
1975
0
  }
1976
1977
0
  bgp_peer_send_gr_capability(s, peer, ext_opt_params);
1978
0
  bgp_peer_send_llgr_capability(s, peer, ext_opt_params);
1979
1980
  /* Software Version capability
1981
   * An implementation is REQUIRED Extended Optional Parameters
1982
   * Length for BGP OPEN Message support as defined in [RFC9072].
1983
   * The inclusion of the Software Version Capability is OPTIONAL.
1984
   * If an implementation supports the inclusion of the capability,
1985
   * the implementation MUST include a configuration switch to enable
1986
   * or disable its use, and that switch MUST be off by default.
1987
   */
1988
0
  if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION) ||
1989
0
      peer->sort == BGP_PEER_IBGP) {
1990
0
    SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_ADV);
1991
0
    stream_putc(s, BGP_OPEN_OPT_CAP);
1992
0
    rcapp = stream_get_endp(s);
1993
0
    ext_opt_params ? stream_putw(s, 0)
1994
0
             : stream_putc(s, 0); /* Capability Length */
1995
0
    stream_putc(s, CAPABILITY_CODE_SOFT_VERSION);
1996
0
    capp = stream_get_endp(s);
1997
0
    stream_putc(s, 0); /* dummy placeholder len */
1998
1999
    /* The Capability Length SHOULD be no greater than 64.
2000
     * This is the limit to allow other capabilities as much
2001
     * space as they require.
2002
     */
2003
0
    len = strlen(cmd_software_version_get());
2004
0
    if (len > BGP_MAX_SOFT_VERSION)
2005
0
      len = BGP_MAX_SOFT_VERSION;
2006
2007
0
    stream_putc(s, len);
2008
0
    stream_put(s, cmd_software_version_get(), len);
2009
2010
    /* Software Version capability Len. */
2011
0
    len = stream_get_endp(s) - rcapp - 1;
2012
0
    ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
2013
0
             : stream_putc_at(s, rcapp, len);
2014
2015
    /* Total Capability Len. */
2016
0
    len = stream_get_endp(s) - capp - 1;
2017
0
    stream_putc_at(s, capp, len);
2018
2019
0
    if (bgp_debug_neighbor_events(peer))
2020
0
      zlog_debug("%s Sending Software Version cap, value: %s",
2021
0
           peer->host, cmd_software_version_get());
2022
0
  }
2023
2024
  /* Total Opt Parm Len. */
2025
0
  len = stream_get_endp(s) - cp - 1;
2026
2027
0
  if (ext_opt_params) {
2028
0
    len = stream_get_endp(s) - eopl - 2;
2029
0
    stream_putw_at(s, eopl, len);
2030
0
  } else {
2031
0
    stream_putc_at(s, cp, len);
2032
0
  }
2033
2034
0
  return len;
2035
0
}