Coverage Report

Created: 2026-06-06 06:50

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
26
{
297
26
  mpc->afi = stream_getw(s);
298
26
  mpc->reserved = stream_getc(s);
299
26
  mpc->safi = stream_getc(s);
300
26
}
301
302
/* Set negotiated capability value. */
303
static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr)
304
26
{
305
26
  struct capability_mp_data mpc;
306
26
  struct stream *s = BGP_INPUT(peer);
307
26
  afi_t afi;
308
26
  safi_t safi;
309
310
  /* Verify length is 4 */
311
26
  if (hdr->length != 4) {
312
3
    flog_warn(
313
3
      EC_BGP_CAPABILITY_INVALID_LENGTH,
314
3
      "MP Cap: Received invalid length %d, non-multiple of 4",
315
3
      hdr->length);
316
3
    return -1;
317
3
  }
318
319
23
  bgp_capability_mp_data(s, &mpc);
320
321
23
  if (bgp_debug_neighbor_events(peer))
322
0
    zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s",
323
23
         peer->host, lookup_msg(capcode_str, hdr->code, NULL),
324
23
         iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
325
326
  /* Convert AFI, SAFI to internal values, check. */
327
23
  if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi))
328
4
    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
0
{
345
0
  if (bgp_debug_neighbor_events(peer))
346
0
    zlog_debug(
347
0
      "%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
348
0
      peer->host, afi, safi, type, mode);
349
0
}
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
3
{
365
3
  struct stream *s = BGP_INPUT(peer);
366
3
  struct capability_mp_data mpc;
367
3
  uint8_t num;
368
3
  iana_afi_t pkt_afi;
369
3
  afi_t afi;
370
3
  iana_safi_t pkt_safi;
371
3
  safi_t safi;
372
3
  uint8_t type;
373
3
  uint8_t mode;
374
3
  uint16_t sm_cap = 0; /* capability send-mode receive */
375
3
  uint16_t rm_cap = 0; /* capability receive-mode receive */
376
3
  int i;
377
378
  /* ORF Entry header */
379
3
  bgp_capability_mp_data(s, &mpc);
380
3
  num = stream_getc(s);
381
3
  pkt_afi = mpc.afi;
382
3
  pkt_safi = mpc.safi;
383
384
3
  if (bgp_debug_neighbor_events(peer))
385
0
    zlog_debug("%s ORF Cap entry for afi/safi: %s/%s", peer->host,
386
3
         iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
387
388
  /* Convert AFI, SAFI to internal values, check. */
389
3
  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
0
  mpc.afi = pkt_afi;
397
0
  mpc.safi = safi;
398
399
  /* validate number field */
400
0
  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
0
  for (i = 0; i < num; i++) {
410
0
    type = stream_getc(s);
411
0
    mode = stream_getc(s);
412
413
    /* ORF Mode error check */
414
0
    switch (mode) {
415
0
    case ORF_MODE_BOTH:
416
0
    case ORF_MODE_SEND:
417
0
    case ORF_MODE_RECEIVE:
418
0
      break;
419
0
    default:
420
0
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
421
0
                   type, mode);
422
0
      continue;
423
0
    }
424
    /* ORF Type and afi/safi error checks */
425
    /* capcode versus type */
426
0
    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
0
    case CAPABILITY_CODE_ORF_OLD:
444
0
      switch (type) {
445
0
      case ORF_TYPE_RESERVED:
446
0
        if (bgp_debug_neighbor_events(peer))
447
0
          zlog_debug(
448
0
            "%s Addr-family %d/%d has reserved ORF type, ignoring",
449
0
            peer->host, afi, safi);
450
0
        break;
451
0
      case ORF_TYPE_PREFIX_OLD:
452
0
        break;
453
0
      default:
454
0
        bgp_capability_orf_not_support(
455
0
          peer, pkt_afi, pkt_safi, type, mode);
456
0
        continue;
457
0
      }
458
0
      break;
459
0
    default:
460
0
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
461
0
                   type, mode);
462
0
      continue;
463
0
    }
464
465
    /* AFI vs SAFI */
466
0
    if (!((afi == AFI_IP && safi == SAFI_UNICAST)
467
0
          || (afi == AFI_IP && safi == SAFI_MULTICAST)
468
0
          || (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
0
    if (bgp_debug_neighbor_events(peer))
475
0
      zlog_debug(
476
0
        "%s OPEN has %s ORF capability as %s for afi/safi: %s/%s",
477
0
        peer->host,
478
0
        lookup_msg(orf_type_str, type, NULL),
479
0
        lookup_msg(orf_mode_str, mode, NULL),
480
0
        iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
481
482
0
    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
0
    } else if (hdr->code == CAPABILITY_CODE_ORF_OLD) {
486
0
      sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
487
0
      rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
488
0
    } else {
489
0
      bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
490
0
                   type, mode);
491
0
      continue;
492
0
    }
493
494
0
    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
0
    case ORF_MODE_SEND:
500
0
      SET_FLAG(peer->af_cap[afi][safi], sm_cap);
501
0
      break;
502
0
    case ORF_MODE_RECEIVE:
503
0
      SET_FLAG(peer->af_cap[afi][safi], rm_cap);
504
0
      break;
505
0
    }
506
0
  }
507
0
  return 0;
508
0
}
509
510
static int bgp_capability_restart(struct peer *peer,
511
          struct capability_header *caphdr)
512
15
{
513
15
  struct stream *s = BGP_INPUT(peer);
514
15
  uint16_t restart_flag_time;
515
15
  size_t end = stream_get_getp(s) + caphdr->length;
516
517
  /* Verify length is a multiple of 4 */
518
15
  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
15
  SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
527
15
  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
15
  if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_R_BIT))
533
4
    SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
534
11
  else
535
11
    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
15
  if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_N_BIT))
541
10
    SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
542
5
  else
543
5
    UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
544
545
15
  UNSET_FLAG(restart_flag_time, 0xF000);
546
15
  peer->v_gr_restart = restart_flag_time;
547
548
15
  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
62
  while (stream_get_getp(s) + 4 <= end) {
564
47
    afi_t afi;
565
47
    safi_t safi;
566
47
    iana_afi_t pkt_afi = stream_getw(s);
567
47
    iana_safi_t pkt_safi = stream_getc(s);
568
47
    uint8_t flag = stream_getc(s);
569
570
    /* Convert AFI, SAFI to internal values, check. */
571
47
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
572
47
      if (bgp_debug_neighbor_events(peer))
573
0
        zlog_debug(
574
47
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Graceful Restart capability for this AFI/SAFI",
575
47
          peer->host, iana_afi2str(pkt_afi),
576
47
          iana_safi2str(pkt_safi));
577
47
    } 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
47
  }
601
15
  return 0;
602
15
}
603
604
static int bgp_capability_llgr(struct peer *peer,
605
             struct capability_header *caphdr)
606
4
{
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
64
#define BGP_CAP_LLGR_MIN_PACKET_LEN 7
619
4
  struct stream *s = BGP_INPUT(peer);
620
4
  size_t end = stream_get_getp(s) + caphdr->length;
621
622
4
  SET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
623
624
64
  while (stream_get_getp(s) + BGP_CAP_LLGR_MIN_PACKET_LEN <= end) {
625
60
    afi_t afi;
626
60
    safi_t safi;
627
60
    iana_afi_t pkt_afi = stream_getw(s);
628
60
    iana_safi_t pkt_safi = stream_getc(s);
629
60
    uint8_t flags = stream_getc(s);
630
60
    uint32_t stale_time = stream_get3(s);
631
632
60
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
633
59
      if (bgp_debug_neighbor_events(peer))
634
0
        zlog_debug(
635
59
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Long-lived Graceful Restart capability for this AFI/SAFI",
636
59
          peer->host, iana_afi2str(pkt_afi),
637
59
          iana_safi2str(pkt_safi));
638
59
    } else if (!peer->afc[afi][safi]
639
0
         || !CHECK_FLAG(peer->af_cap[afi][safi],
640
1
            PEER_CAP_RESTART_AF_RCV)) {
641
1
      if (bgp_debug_neighbor_events(peer))
642
0
        zlog_debug(
643
1
          "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Long-lived Graceful Restart capability",
644
1
          peer->host, iana_afi2str(pkt_afi),
645
1
          iana_safi2str(pkt_safi));
646
1
    } 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
60
  }
659
660
4
  return 0;
661
4
}
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
200
{
666
200
  SET_FLAG(peer->cap, PEER_CAP_AS4_RCV);
667
668
200
  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
198
  as_t as4 = stream_getl(BGP_INPUT(peer));
676
677
198
  if (BGP_DEBUG(as4, AS4))
678
0
    zlog_debug(
679
198
      "%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
680
198
      peer->host, as4);
681
198
  return as4;
682
200
}
683
684
static int bgp_capability_ext_message(struct peer *peer,
685
              struct capability_header *hdr)
686
2
{
687
2
  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
2
  SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV);
696
697
2
  return 0;
698
2
}
699
700
static int bgp_capability_addpath(struct peer *peer,
701
          struct capability_header *hdr)
702
42
{
703
42
  struct stream *s = BGP_INPUT(peer);
704
42
  size_t end = stream_get_getp(s) + hdr->length;
705
706
42
  SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
707
708
  /* Verify length is a multiple of 4 */
709
42
  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
168
  while (stream_get_getp(s) + 4 <= end) {
718
126
    afi_t afi;
719
126
    safi_t safi;
720
126
    iana_afi_t pkt_afi = stream_getw(s);
721
126
    iana_safi_t pkt_safi = stream_getc(s);
722
126
    uint8_t send_receive = stream_getc(s);
723
724
126
    if (bgp_debug_neighbor_events(peer))
725
0
      zlog_debug(
726
126
        "%s OPEN has %s capability for afi/safi: %s/%s%s%s",
727
126
        peer->host,
728
126
        lookup_msg(capcode_str, hdr->code, NULL),
729
126
        iana_afi2str(pkt_afi), iana_safi2str(pkt_safi),
730
126
        (send_receive & BGP_ADDPATH_RX) ? ", receive"
731
126
                : "",
732
126
        (send_receive & BGP_ADDPATH_TX) ? ", transmit"
733
126
                : "");
734
735
    /* Convert AFI, SAFI to internal values, check. */
736
126
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
737
50
      if (bgp_debug_neighbor_events(peer))
738
0
        zlog_debug(
739
50
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Addpath Attribute for this AFI/SAFI",
740
50
          peer->host, iana_afi2str(pkt_afi),
741
50
          iana_safi2str(pkt_safi));
742
50
      continue;
743
76
    } 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
76
    if (send_receive & BGP_ADDPATH_RX)
753
49
      SET_FLAG(peer->af_cap[afi][safi],
754
76
         PEER_CAP_ADDPATH_AF_RX_RCV);
755
756
76
    if (send_receive & BGP_ADDPATH_TX)
757
23
      SET_FLAG(peer->af_cap[afi][safi],
758
76
         PEER_CAP_ADDPATH_AF_TX_RCV);
759
76
  }
760
761
42
  return 0;
762
42
}
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
86
  while (stream_get_getp(s) + 6 <= end) {
779
84
    iana_afi_t pkt_afi = stream_getw(s);
780
84
    afi_t afi;
781
84
    iana_safi_t pkt_safi = stream_getw(s);
782
84
    safi_t safi;
783
84
    iana_afi_t pkt_nh_afi = stream_getw(s);
784
84
    afi_t nh_afi;
785
786
84
    if (bgp_debug_neighbor_events(peer))
787
0
      zlog_debug(
788
84
        "%s Received with afi/safi/next-hop afi: %s/%s/%u",
789
84
        peer->host, iana_afi2str(pkt_afi),
790
84
        iana_safi2str(pkt_safi), pkt_nh_afi);
791
792
    /* Convert AFI, SAFI to internal values, check. */
793
84
    if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
794
84
      if (bgp_debug_neighbor_events(peer))
795
0
        zlog_debug(
796
84
          "%s Addr-family %s/%s(afi/safi) not supported. Ignore the ENHE Attribute for this AFI/SAFI",
797
84
          peer->host, iana_afi2str(pkt_afi),
798
84
          iana_safi2str(pkt_safi));
799
84
      continue;
800
84
    }
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
9
{
838
9
  struct stream *s = BGP_INPUT(peer);
839
9
  char str[BGP_MAX_HOSTNAME + 1];
840
9
  size_t end = stream_get_getp(s) + hdr->length;
841
9
  uint8_t len;
842
843
9
  SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
844
845
9
  len = stream_getc(s);
846
9
  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
9
  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
9
  } else if (len)
859
0
    stream_get(str, s, len);
860
861
9
  if (len) {
862
0
    str[len] = '\0';
863
864
0
    XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
865
0
    XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
866
867
0
    peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
868
0
  }
869
870
9
  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
9
  len = stream_getc(s);
879
9
  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
9
  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
9
  } else if (len)
892
0
    stream_get(str, s, len);
893
894
9
  if (len) {
895
0
    str[len] = '\0';
896
897
0
    XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
898
899
0
    peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
900
0
  }
901
902
9
  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
9
  return 0;
908
9
}
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
1
    flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
915
1
        "Role: Received invalid length %d", hdr->length);
916
1
    return -1;
917
1
  }
918
0
  uint8_t role = stream_getc(BGP_INPUT(peer));
919
920
0
  peer->remote_role = role;
921
0
  return 0;
922
1
}
923
924
static int bgp_capability_software_version(struct peer *peer,
925
             struct capability_header *hdr)
926
7
{
927
7
  struct stream *s = BGP_INPUT(peer);
928
7
  char str[BGP_MAX_SOFT_VERSION + 1];
929
7
  size_t end = stream_get_getp(s) + hdr->length;
930
7
  uint8_t len;
931
932
7
  SET_FLAG(peer->cap, PEER_CAP_SOFT_VERSION_RCV);
933
934
7
  len = stream_getc(s);
935
7
  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
7
  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
7
  } else if (len) {
951
0
    stream_get(str, s, len);
952
0
  }
953
954
7
  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
7
  return 0;
967
7
}
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
81
{
979
81
  int ret;
980
81
  struct stream *s = BGP_INPUT(peer);
981
81
  size_t end = stream_get_getp(s) + length;
982
81
  uint16_t restart_flag_time = 0;
983
984
81
  assert(STREAM_READABLE(s) >= length);
985
986
2.02k
  while (stream_get_getp(s) < end) {
987
1.97k
    size_t start;
988
1.97k
    uint8_t *sp = stream_pnt(s);
989
1.97k
    struct capability_header caphdr;
990
991
1.97k
    ret = 0;
992
    /* We need at least capability code and capability length. */
993
1.97k
    if (stream_get_getp(s) + 2 > end) {
994
3
      zlog_info("%s Capability length error (< header)",
995
3
          peer->host);
996
3
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
997
3
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
998
3
      return -1;
999
3
    }
1000
1001
1.97k
    caphdr.code = stream_getc(s);
1002
1.97k
    caphdr.length = stream_getc(s);
1003
1.97k
    start = stream_get_getp(s);
1004
1005
    /* Capability length check sanity check. */
1006
1.97k
    if (start + caphdr.length > end) {
1007
32
      zlog_info("%s Capability length error (< length)",
1008
32
          peer->host);
1009
32
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1010
32
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1011
32
      return -1;
1012
32
    }
1013
1014
1.94k
    if (bgp_debug_neighbor_events(peer))
1015
0
      zlog_debug("%s OPEN has %s capability (%u), length %u",
1016
1.94k
           peer->host,
1017
1.94k
           lookup_msg(capcode_str, caphdr.code, NULL),
1018
1.94k
           caphdr.code, caphdr.length);
1019
1020
    /* Length sanity check, type-specific, for known capabilities */
1021
1.94k
    switch (caphdr.code) {
1022
27
    case CAPABILITY_CODE_MP:
1023
116
    case CAPABILITY_CODE_REFRESH:
1024
150
    case CAPABILITY_CODE_REFRESH_OLD:
1025
150
    case CAPABILITY_CODE_ORF:
1026
153
    case CAPABILITY_CODE_ORF_OLD:
1027
168
    case CAPABILITY_CODE_RESTART:
1028
322
    case CAPABILITY_CODE_AS4:
1029
364
    case CAPABILITY_CODE_ADDPATH:
1030
364
    case CAPABILITY_CODE_DYNAMIC:
1031
370
    case CAPABILITY_CODE_DYNAMIC_OLD:
1032
372
    case CAPABILITY_CODE_ENHE:
1033
381
    case CAPABILITY_CODE_FQDN:
1034
384
    case CAPABILITY_CODE_ENHANCED_RR:
1035
386
    case CAPABILITY_CODE_EXT_MESSAGE:
1036
387
    case CAPABILITY_CODE_ROLE:
1037
394
    case CAPABILITY_CODE_SOFT_VERSION:
1038
      /* Check length. */
1039
394
      if (caphdr.length < cap_minsizes[caphdr.code]) {
1040
2
        zlog_info(
1041
2
          "%s %s Capability length error: got %u, expected at least %u",
1042
2
          peer->host,
1043
2
          lookup_msg(capcode_str, caphdr.code,
1044
2
               NULL),
1045
2
          caphdr.length,
1046
2
          (unsigned)cap_minsizes[caphdr.code]);
1047
2
        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1048
2
            BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1049
2
        return -1;
1050
2
      }
1051
392
      if (caphdr.length
1052
334
          && 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.94k
    default:
1066
1.94k
      break;
1067
1.94k
    }
1068
1069
1.94k
    switch (caphdr.code) {
1070
26
    case CAPABILITY_CODE_MP: {
1071
26
      *mp_capability = 1;
1072
1073
      /* Ignore capability when override-capability is set. */
1074
26
      if (!CHECK_FLAG(peer->flags,
1075
26
          PEER_FLAG_OVERRIDE_CAPABILITY)) {
1076
        /* Set negotiated value. */
1077
26
        ret = bgp_capability_mp(peer, &caphdr);
1078
1079
        /* Unsupported Capability. */
1080
26
        if (ret < 0) {
1081
          /* Store return data. */
1082
26
          memcpy(*error, sp, caphdr.length + 2);
1083
26
          *error += caphdr.length + 2;
1084
26
        }
1085
26
        ret = 0; /* Don't return error for this */
1086
26
      }
1087
26
    } break;
1088
3
    case CAPABILITY_CODE_ENHANCED_RR:
1089
92
    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
3
        SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_RCV);
1094
123
      else if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
1095
34
        SET_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV);
1096
89
      else
1097
89
        SET_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV);
1098
126
    } break;
1099
0
    case CAPABILITY_CODE_ORF:
1100
3
    case CAPABILITY_CODE_ORF_OLD:
1101
3
      ret = bgp_capability_orf_entry(peer, &caphdr);
1102
3
      break;
1103
15
    case CAPABILITY_CODE_RESTART:
1104
15
      ret = bgp_capability_restart(peer, &caphdr);
1105
15
      break;
1106
4
    case CAPABILITY_CODE_LLGR:
1107
4
      ret = bgp_capability_llgr(peer, &caphdr);
1108
4
      break;
1109
0
    case CAPABILITY_CODE_DYNAMIC:
1110
6
    case CAPABILITY_CODE_DYNAMIC_OLD:
1111
6
      SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV);
1112
6
      break;
1113
153
    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
153
      if (!bgp_capability_as4(peer, &caphdr))
1121
2
        ret = -1;
1122
153
      break;
1123
42
    case CAPABILITY_CODE_ADDPATH:
1124
42
      ret = bgp_capability_addpath(peer, &caphdr);
1125
42
      break;
1126
2
    case CAPABILITY_CODE_ENHE:
1127
2
      ret = bgp_capability_enhe(peer, &caphdr);
1128
2
      break;
1129
2
    case CAPABILITY_CODE_EXT_MESSAGE:
1130
2
      ret = bgp_capability_ext_message(peer, &caphdr);
1131
2
      break;
1132
9
    case CAPABILITY_CODE_FQDN:
1133
9
      ret = bgp_capability_hostname(peer, &caphdr);
1134
9
      break;
1135
1
    case CAPABILITY_CODE_ROLE:
1136
1
      ret = bgp_capability_role(peer, &caphdr);
1137
1
      break;
1138
7
    case CAPABILITY_CODE_SOFT_VERSION:
1139
7
      ret = bgp_capability_software_version(peer, &caphdr);
1140
7
      break;
1141
1.54k
    default:
1142
1.54k
      if (caphdr.code > 128) {
1143
        /* We don't send Notification for unknown vendor
1144
           specific
1145
           capabilities.  It seems reasonable for now...
1146
           */
1147
130
        flog_warn(EC_BGP_CAPABILITY_VENDOR,
1148
130
            "%s Vendor specific capability %d",
1149
130
            peer->host, caphdr.code);
1150
1.41k
      } else {
1151
1.41k
        flog_warn(
1152
1.41k
          EC_BGP_CAPABILITY_UNKNOWN,
1153
1.41k
          "%s unrecognized capability code: %d - ignored",
1154
1.41k
          peer->host, caphdr.code);
1155
1.41k
        memcpy(*error, sp, caphdr.length + 2);
1156
1.41k
        *error += caphdr.length + 2;
1157
1.41k
      }
1158
1.94k
    }
1159
1160
1.94k
    if (ret < 0) {
1161
3
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1162
3
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1163
3
      return -1;
1164
3
    }
1165
1.93k
    if (stream_get_getp(s) != (start + caphdr.length)) {
1166
443
      if (stream_get_getp(s) > (start + caphdr.length))
1167
0
        flog_warn(
1168
443
          EC_BGP_CAPABILITY_INVALID_LENGTH,
1169
443
          "%s Cap-parser for %s read past cap-length, %u!",
1170
443
          peer->host,
1171
443
          lookup_msg(capcode_str, caphdr.code,
1172
443
               NULL),
1173
443
          caphdr.length);
1174
443
      stream_set_getp(s, start + caphdr.length);
1175
443
    }
1176
1177
1.93k
    if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
1178
1.74k
      UNSET_FLAG(restart_flag_time, 0xF000);
1179
1.74k
      peer->v_gr_restart = restart_flag_time;
1180
1.74k
    }
1181
1.93k
  }
1182
41
  return 0;
1183
81
}
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
5
      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
64
{
1231
64
  struct stream *s = BGP_INPUT(peer);
1232
64
  size_t orig_getp = stream_get_getp(s);
1233
64
  size_t end = orig_getp + length;
1234
64
  as_t as4 = 0;
1235
1236
64
  if (BGP_DEBUG(as4, AS4))
1237
0
    zlog_debug(
1238
64
      "%s [AS4] rcv OPEN w/ OPTION parameter len: %u, peeking for as4",
1239
64
      peer->host, length);
1240
  /* the error cases we DONT handle, we ONLY try to read as4 out of
1241
   * correctly formatted options.
1242
   */
1243
250
  while (stream_get_getp(s) < end) {
1244
250
    uint8_t opt_type;
1245
250
    uint16_t opt_length;
1246
1247
    /* Ensure we can read the option type */
1248
250
    if (stream_get_getp(s) + 1 > end)
1249
0
      goto end;
1250
1251
    /* Fetch the option type */
1252
250
    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
250
    if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
1261
250
      if (stream_get_getp(s) + 2 > end)
1262
4
        goto end;
1263
1264
246
      opt_length = stream_getw(s);
1265
246
    } 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
246
    if (stream_get_getp(s) + opt_length > end)
1274
11
      goto end;
1275
1276
235
    if (opt_type == BGP_OPEN_OPT_CAP) {
1277
55
      unsigned long capd_start = stream_get_getp(s);
1278
55
      unsigned long capd_end = capd_start + opt_length;
1279
1280
55
      assert(capd_end <= end);
1281
1282
164
      while (stream_get_getp(s) < capd_end) {
1283
158
        struct capability_header hdr;
1284
1285
158
        if (stream_get_getp(s) + 2 > capd_end)
1286
2
          goto end;
1287
1288
156
        hdr.code = stream_getc(s);
1289
156
        hdr.length = stream_getc(s);
1290
1291
156
        if ((stream_get_getp(s) + hdr.length)
1292
156
            > capd_end)
1293
0
          goto end;
1294
1295
156
        if (hdr.code == CAPABILITY_CODE_AS4) {
1296
47
          if (BGP_DEBUG(as4, AS4))
1297
0
            zlog_debug(
1298
47
              "[AS4] found AS4 capability, about to parse");
1299
47
          as4 = bgp_capability_as4(peer, &hdr);
1300
1301
47
          goto end;
1302
47
        }
1303
109
        stream_forward_getp(s, hdr.length);
1304
109
      }
1305
55
    }
1306
235
  }
1307
1308
64
end:
1309
64
  stream_set_getp(s, orig_getp);
1310
64
  return as4;
1311
64
}
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
46
{
1321
46
  int ret = 0;
1322
46
  uint8_t *error;
1323
46
  uint8_t error_data[BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE];
1324
46
  struct stream *s = BGP_INPUT(peer);
1325
46
  size_t end = stream_get_getp(s) + length;
1326
1327
46
  error = error_data;
1328
1329
46
  if (bgp_debug_neighbor_events(peer))
1330
0
    zlog_debug("%s rcv OPEN w/ OPTION parameter len: %u",
1331
46
         peer->host, length);
1332
1333
  /* Unset any previously received GR capability. */
1334
46
  UNSET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
1335
1336
87
  while (stream_get_getp(s) < end) {
1337
82
    uint8_t opt_type;
1338
82
    uint16_t opt_length;
1339
1340
    /*
1341
     * Check that we can read the opt_type and fetch it
1342
     */
1343
82
    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
82
    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
82
    if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
1356
82
      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
82
      opt_length = stream_getw(s);
1364
82
    } 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
82
    if (STREAM_READABLE(s) < opt_length) {
1377
1
      zlog_info("%s Option length error (%d)", peer->host,
1378
1
          opt_length);
1379
1
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1380
1
          BGP_NOTIFY_OPEN_MALFORMED_ATTR);
1381
1
      return -1;
1382
1
    }
1383
1384
81
    if (bgp_debug_neighbor_events(peer))
1385
0
      zlog_debug(
1386
81
        "%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
1387
81
        peer->host, opt_type,
1388
81
        opt_type == BGP_OPEN_OPT_CAP ? "Capability"
1389
81
                   : "Unknown",
1390
81
        opt_length);
1391
1392
81
    switch (opt_type) {
1393
81
    case BGP_OPEN_OPT_CAP:
1394
81
      ret = bgp_capability_parse(peer, opt_length,
1395
81
               mp_capability, &error);
1396
81
      break;
1397
0
    default:
1398
0
      bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
1399
0
          BGP_NOTIFY_OPEN_UNSUP_PARAM);
1400
0
      ret = -1;
1401
0
      break;
1402
81
    }
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
81
    if (ret < 0)
1409
40
      return -1;
1410
81
  }
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
1
     && 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
2
        && !peer->afc_nego[AFI_IP][SAFI_MULTICAST]
1450
2
        && !peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
1451
2
        && !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
}