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