blob: af711cc8ceba87bea72958983bca69b7b138767f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP open message handling
2 Copyright (C) 1998, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
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"
Paul Jakma6d582722007-08-06 15:21:45 +000029#include "memory.h"
paul718e3742002-12-13 20:15:29 +000030
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_attr.h"
33#include "bgpd/bgp_debug.h"
34#include "bgpd/bgp_fsm.h"
35#include "bgpd/bgp_packet.h"
36#include "bgpd/bgp_open.h"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000037#include "bgpd/bgp_aspath.h"
hasso538621f2004-05-21 09:31:30 +000038#include "bgpd/bgp_vty.h"
39
paul718e3742002-12-13 20:15:29 +000040/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
41 negotiate remote peer supports extentions or not. But if
42 remote-peer doesn't supports negotiation process itself. We would
43 like to do manual configuration.
44
45 So there is many configurable point. First of all we want set each
46 peer whether we send capability negotiation to the peer or not.
47 Next, if we send capability to the peer we want to set my capabilty
48 inforation at each peer. */
49
50void
51bgp_capability_vty_out (struct vty *vty, struct peer *peer)
52{
paul5228ad22004-06-04 17:58:18 +000053 char *pnt;
54 char *end;
Paul Jakma6d582722007-08-06 15:21:45 +000055 struct capability_mp_data mpc;
56 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +000057
58 pnt = peer->notify.data;
59 end = pnt + peer->notify.length;
Paul Jakma6d582722007-08-06 15:21:45 +000060
paul718e3742002-12-13 20:15:29 +000061 while (pnt < end)
62 {
Paul Jakma6d582722007-08-06 15:21:45 +000063 if (pnt + sizeof (struct capability_mp_data) + 2 > end)
paul718e3742002-12-13 20:15:29 +000064 return;
Paul Jakma6d582722007-08-06 15:21:45 +000065
66 hdr = (struct capability_header *)pnt;
67 if (pnt + hdr->length + 2 > end)
paul718e3742002-12-13 20:15:29 +000068 return;
69
Paul Jakma6d582722007-08-06 15:21:45 +000070 memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
71
72 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +000073 {
74 vty_out (vty, " Capability error for: Multi protocol ");
75
Paul Jakma6d582722007-08-06 15:21:45 +000076 switch (ntohs (mpc.afi))
paul718e3742002-12-13 20:15:29 +000077 {
78 case AFI_IP:
79 vty_out (vty, "AFI IPv4, ");
80 break;
81 case AFI_IP6:
82 vty_out (vty, "AFI IPv6, ");
83 break;
84 default:
Paul Jakma6d582722007-08-06 15:21:45 +000085 vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
paul718e3742002-12-13 20:15:29 +000086 break;
87 }
Paul Jakma6d582722007-08-06 15:21:45 +000088 switch (mpc.safi)
paul718e3742002-12-13 20:15:29 +000089 {
90 case SAFI_UNICAST:
91 vty_out (vty, "SAFI Unicast");
92 break;
93 case SAFI_MULTICAST:
94 vty_out (vty, "SAFI Multicast");
95 break;
Denis Ovsienko42e6d742011-07-14 12:36:19 +040096 case SAFI_MPLS_LABELED_VPN:
97 vty_out (vty, "SAFI MPLS-labeled VPN");
paul718e3742002-12-13 20:15:29 +000098 break;
99 default:
Paul Jakma6d582722007-08-06 15:21:45 +0000100 vty_out (vty, "SAFI Unknown %d ", mpc.safi);
paul718e3742002-12-13 20:15:29 +0000101 break;
102 }
103 vty_out (vty, "%s", VTY_NEWLINE);
104 }
Paul Jakma6d582722007-08-06 15:21:45 +0000105 else if (hdr->code >= 128)
paul718e3742002-12-13 20:15:29 +0000106 vty_out (vty, " Capability error: vendor specific capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000107 hdr->code);
paul718e3742002-12-13 20:15:29 +0000108 else
109 vty_out (vty, " Capability error: unknown capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000110 hdr->code);
paul718e3742002-12-13 20:15:29 +0000111
Paul Jakma6d582722007-08-06 15:21:45 +0000112 pnt += hdr->length + 2;
paul718e3742002-12-13 20:15:29 +0000113 }
114}
115
Paul Jakma6d582722007-08-06 15:21:45 +0000116static void
117bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
118{
119 mpc->afi = stream_getw (s);
120 mpc->reserved = stream_getc (s);
121 mpc->safi = stream_getc (s);
122}
123
124int
125bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
126{
Paul Jakma6d582722007-08-06 15:21:45 +0000127 switch (afi)
128 {
129 case AFI_IP:
130#ifdef HAVE_IPV6
131 case AFI_IP6:
132#endif
133 switch (*safi)
134 {
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400135 /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
136 case SAFI_MPLS_LABELED_VPN:
Paul Jakma6d582722007-08-06 15:21:45 +0000137 *safi = SAFI_MPLS_VPN;
138 case SAFI_UNICAST:
139 case SAFI_MULTICAST:
140 case SAFI_MPLS_VPN:
141 return 1;
142 }
143 }
144 zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
145
146 return 0;
147}
148
paul718e3742002-12-13 20:15:29 +0000149/* Set negotiated capability value. */
paul94f2b392005-06-28 12:44:16 +0000150static int
Paul Jakma6d582722007-08-06 15:21:45 +0000151bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
paul718e3742002-12-13 20:15:29 +0000152{
Paul Jakma6d582722007-08-06 15:21:45 +0000153 struct capability_mp_data mpc;
154 struct stream *s = BGP_INPUT (peer);
155
156 bgp_capability_mp_data (s, &mpc);
157
158 if (BGP_DEBUG (normal, NORMAL))
159 zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
160 peer->host, mpc.afi, mpc.safi);
161
162 if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
163 return -1;
164
165 /* Now safi remapped, and afi/safi are valid array indices */
166 peer->afc_recv[mpc.afi][mpc.safi] = 1;
167
168 if (peer->afc[mpc.afi][mpc.safi])
Paul Jakmae08286b2007-09-18 12:11:26 +0000169 peer->afc_nego[mpc.afi][mpc.safi] = 1;
Paul Jakma6d582722007-08-06 15:21:45 +0000170 else
171 return -1;
paul718e3742002-12-13 20:15:29 +0000172
173 return 0;
174}
175
paul94f2b392005-06-28 12:44:16 +0000176static void
paul718e3742002-12-13 20:15:29 +0000177bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
178 u_char type, u_char mode)
179{
180 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000181 zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
paul718e3742002-12-13 20:15:29 +0000182 peer->host, afi, safi, type, mode);
183}
184
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700185static const struct message orf_type_str[] =
paul718e3742002-12-13 20:15:29 +0000186{
Paul Jakma6d582722007-08-06 15:21:45 +0000187 { ORF_TYPE_PREFIX, "Prefixlist" },
188 { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
189};
Balaji.G837d16c2012-09-26 14:09:10 +0530190static const int orf_type_str_max = array_size(orf_type_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000191
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700192static const struct message orf_mode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000193{
194 { ORF_MODE_RECEIVE, "Receive" },
195 { ORF_MODE_SEND, "Send" },
196 { ORF_MODE_BOTH, "Both" },
197};
Balaji.G837d16c2012-09-26 14:09:10 +0530198static const int orf_mode_str_max = array_size(orf_mode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000199
200static int
201bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
202{
203 struct stream *s = BGP_INPUT (peer);
204 struct capability_orf_entry entry;
205 afi_t afi;
206 safi_t safi;
paul718e3742002-12-13 20:15:29 +0000207 u_char type;
208 u_char mode;
209 u_int16_t sm_cap = 0; /* capability send-mode receive */
210 u_int16_t rm_cap = 0; /* capability receive-mode receive */
211 int i;
212
Paul Jakma6d582722007-08-06 15:21:45 +0000213 /* ORF Entry header */
214 bgp_capability_mp_data (s, &entry.mpc);
215 entry.num = stream_getc (s);
216 afi = entry.mpc.afi;
217 safi = entry.mpc.safi;
218
paul718e3742002-12-13 20:15:29 +0000219 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma6d582722007-08-06 15:21:45 +0000220 zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
221 peer->host, entry.mpc.afi, entry.mpc.safi);
paul718e3742002-12-13 20:15:29 +0000222
223 /* Check AFI and SAFI. */
Paul Jakma6d582722007-08-06 15:21:45 +0000224 if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
paul718e3742002-12-13 20:15:29 +0000225 {
Paul Jakma6d582722007-08-06 15:21:45 +0000226 zlog_info ("%s Addr-family %d/%d not supported."
227 " Ignoring the ORF capability",
228 peer->host, entry.mpc.afi, entry.mpc.safi);
229 return 0;
230 }
231
232 /* validate number field */
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400233 if (sizeof (struct capability_orf_entry) + (entry.num * 2) != hdr->length)
Paul Jakma6d582722007-08-06 15:21:45 +0000234 {
235 zlog_info ("%s ORF Capability entry length error,"
236 " Cap length %u, num %u",
237 peer->host, hdr->length, entry.num);
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
paul718e3742002-12-13 20:15:29 +0000239 return -1;
240 }
241
Paul Jakma6d582722007-08-06 15:21:45 +0000242 for (i = 0 ; i < entry.num ; i++)
paul718e3742002-12-13 20:15:29 +0000243 {
Paul Jakma6d582722007-08-06 15:21:45 +0000244 type = stream_getc(s);
245 mode = stream_getc(s);
246
paul718e3742002-12-13 20:15:29 +0000247 /* ORF Mode error check */
Paul Jakma6d582722007-08-06 15:21:45 +0000248 switch (mode)
249 {
250 case ORF_MODE_BOTH:
251 case ORF_MODE_SEND:
252 case ORF_MODE_RECEIVE:
253 break;
254 default:
255 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
256 continue;
paul718e3742002-12-13 20:15:29 +0000257 }
Paul Jakma6d582722007-08-06 15:21:45 +0000258 /* ORF Type and afi/safi error checks */
259 /* capcode versus type */
260 switch (hdr->code)
261 {
262 case CAPABILITY_CODE_ORF:
263 switch (type)
264 {
265 case ORF_TYPE_PREFIX:
266 break;
267 default:
268 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
269 continue;
270 }
271 break;
272 case CAPABILITY_CODE_ORF_OLD:
273 switch (type)
274 {
275 case ORF_TYPE_PREFIX_OLD:
276 break;
277 default:
278 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
279 continue;
280 }
281 break;
282 default:
283 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
284 continue;
285 }
286
287 /* AFI vs SAFI */
288 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
289 || (afi == AFI_IP && safi == SAFI_MULTICAST)
290 || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
291 {
292 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
293 continue;
294 }
295
296 if (BGP_DEBUG (normal, NORMAL))
297 zlog_debug ("%s OPEN has %s ORF capability"
298 " as %s for afi/safi: %d/%d",
299 peer->host, LOOKUP (orf_type_str, type),
300 LOOKUP (orf_mode_str, mode),
301 entry.mpc.afi, safi);
paul718e3742002-12-13 20:15:29 +0000302
Paul Jakma6d582722007-08-06 15:21:45 +0000303 if (hdr->code == CAPABILITY_CODE_ORF)
paul718e3742002-12-13 20:15:29 +0000304 {
Paul Jakma6d582722007-08-06 15:21:45 +0000305 sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
306 rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
paul718e3742002-12-13 20:15:29 +0000307 }
Paul Jakma6d582722007-08-06 15:21:45 +0000308 else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
paul718e3742002-12-13 20:15:29 +0000309 {
Paul Jakma6d582722007-08-06 15:21:45 +0000310 sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
311 rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
paul718e3742002-12-13 20:15:29 +0000312 }
313 else
314 {
315 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
316 continue;
317 }
318
319 switch (mode)
320 {
321 case ORF_MODE_BOTH:
322 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
323 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
324 break;
325 case ORF_MODE_SEND:
326 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
327 break;
328 case ORF_MODE_RECEIVE:
329 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
330 break;
331 }
332 }
333 return 0;
334}
335
paul94f2b392005-06-28 12:44:16 +0000336static int
Paul Jakma6d582722007-08-06 15:21:45 +0000337bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
338{
339 struct stream *s = BGP_INPUT (peer);
340 u_int16_t restart_flag_time;
341 int restart_bit = 0;
342 size_t end = stream_get_getp (s) + caphdr->length;
343
344 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
345 restart_flag_time = stream_getw(s);
346 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
347 restart_bit = 1;
348 UNSET_FLAG (restart_flag_time, 0xF000);
349 peer->v_gr_restart = restart_flag_time;
350
351 if (BGP_DEBUG (normal, NORMAL))
352 {
353 zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
354 zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
355 peer->host, restart_bit ? " " : " not ",
356 peer->v_gr_restart);
357 }
358
Peter Pentchev21cc7692011-09-12 16:30:31 +0400359 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000360 {
361 afi_t afi = stream_getw (s);
362 safi_t safi = stream_getc (s);
363 u_char flag = stream_getc (s);
364
365 if (!bgp_afi_safi_valid_indices (afi, &safi))
366 {
367 if (BGP_DEBUG (normal, NORMAL))
368 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
369 " Ignore the Graceful Restart capability",
370 peer->host, afi, safi);
371 }
372 else if (!peer->afc[afi][safi])
373 {
374 if (BGP_DEBUG (normal, NORMAL))
375 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
376 " Ignore the Graceful Restart capability",
377 peer->host, afi, safi);
378 }
379 else
380 {
381 if (BGP_DEBUG (normal, NORMAL))
382 zlog_debug ("%s Address family %s is%spreserved", peer->host,
383 afi_safi_print (afi, safi),
384 CHECK_FLAG (peer->af_cap[afi][safi],
385 PEER_CAP_RESTART_AF_PRESERVE_RCV)
386 ? " " : " not ");
387
388 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
389 if (CHECK_FLAG (flag, RESTART_F_BIT))
390 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
391
392 }
393 }
394 return 0;
395}
396
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000397static as_t
398bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
399{
Paul Jakma58617392012-01-09 20:59:26 +0000400 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
401
402 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
403 {
404 zlog_err ("%s AS4 capability has incorrect data length %d",
405 peer->host, hdr->length);
406 return 0;
407 }
408
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000409 as_t as4 = stream_getl (BGP_INPUT(peer));
410
411 if (BGP_DEBUG (as4, AS4))
412 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
413 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000414 return as4;
415}
416
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700417static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000418{
Paul Jakma6d582722007-08-06 15:21:45 +0000419 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
420 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
421 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
422 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
423 { CAPABILITY_CODE_AS4, "4-octet AS number" },
424 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
425 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
426 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
427};
Balaji.G837d16c2012-09-26 14:09:10 +0530428static const int capcode_str_max = array_size(capcode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000429
430/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700431static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000432{
433 [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
434 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
435 [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
Paul Jakma370b64a2007-12-22 16:49:52 +0000436 [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
Paul Jakma6d582722007-08-06 15:21:45 +0000437 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
438 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
439 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
440 [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
441};
442
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800443/**
444 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000445 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800446 *
447 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
448 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000449 */
450static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800451bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
452 u_char **error)
paul718e3742002-12-13 20:15:29 +0000453{
454 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000455 struct stream *s = BGP_INPUT (peer);
456 size_t end = stream_get_getp (s) + length;
457
458 assert (STREAM_READABLE (s) >= length);
459
460 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000461 {
Paul Jakma6d582722007-08-06 15:21:45 +0000462 size_t start;
463 u_char *sp = stream_pnt (s);
464 struct capability_header caphdr;
465
paul718e3742002-12-13 20:15:29 +0000466 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000467 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000468 {
Paul Jakma6d582722007-08-06 15:21:45 +0000469 zlog_info ("%s Capability length error (< header)", peer->host);
paul718e3742002-12-13 20:15:29 +0000470 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
471 return -1;
472 }
Paul Jakma6d582722007-08-06 15:21:45 +0000473
474 caphdr.code = stream_getc (s);
475 caphdr.length = stream_getc (s);
476 start = stream_get_getp (s);
477
478 /* Capability length check sanity check. */
479 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000480 {
Paul Jakma6d582722007-08-06 15:21:45 +0000481 zlog_info ("%s Capability length error (< length)", peer->host);
paul718e3742002-12-13 20:15:29 +0000482 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
483 return -1;
484 }
Paul Jakma6d582722007-08-06 15:21:45 +0000485
486 if (BGP_DEBUG (normal, NORMAL))
487 zlog_debug ("%s OPEN has %s capability (%u), length %u",
488 peer->host,
489 LOOKUP (capcode_str, caphdr.code),
490 caphdr.code, caphdr.length);
491
492 /* Length sanity check, type-specific, for known capabilities */
493 switch (caphdr.code)
494 {
495 case CAPABILITY_CODE_MP:
496 case CAPABILITY_CODE_REFRESH:
497 case CAPABILITY_CODE_REFRESH_OLD:
498 case CAPABILITY_CODE_ORF:
499 case CAPABILITY_CODE_ORF_OLD:
500 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000501 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000502 case CAPABILITY_CODE_DYNAMIC:
503 /* Check length. */
504 if (caphdr.length < cap_minsizes[caphdr.code])
505 {
506 zlog_info ("%s %s Capability length error: got %u,"
507 " expected at least %u",
508 peer->host,
509 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700510 caphdr.length,
511 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma6d582722007-08-06 15:21:45 +0000512 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
513 return -1;
514 }
515 /* we deliberately ignore unknown codes, see below */
516 default:
517 break;
518 }
519
520 switch (caphdr.code)
521 {
522 case CAPABILITY_CODE_MP:
523 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800524 *mp_capability = 1;
525
Paul Jakma6d582722007-08-06 15:21:45 +0000526 /* Ignore capability when override-capability is set. */
527 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
528 {
529 /* Set negotiated value. */
530 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000531
Paul Jakma6d582722007-08-06 15:21:45 +0000532 /* Unsupported Capability. */
533 if (ret < 0)
534 {
535 /* Store return data. */
536 memcpy (*error, sp, caphdr.length + 2);
537 *error += caphdr.length + 2;
538 }
539 }
540 }
541 break;
542 case CAPABILITY_CODE_REFRESH:
543 case CAPABILITY_CODE_REFRESH_OLD:
544 {
545 /* BGP refresh capability */
546 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
547 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
548 else
549 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
550 }
551 break;
552 case CAPABILITY_CODE_ORF:
553 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400554 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000555 return -1;
556 break;
557 case CAPABILITY_CODE_RESTART:
558 if (bgp_capability_restart (peer, &caphdr))
559 return -1;
560 break;
561 case CAPABILITY_CODE_DYNAMIC:
562 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
563 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000564 case CAPABILITY_CODE_AS4:
565 /* Already handled as a special-case parsing of the capabilities
566 * at the beginning of OPEN processing. So we care not a jot
567 * for the value really, only error case.
568 */
569 if (!bgp_capability_as4 (peer, &caphdr))
570 return -1;
571 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000572 default:
573 if (caphdr.code > 128)
574 {
575 /* We don't send Notification for unknown vendor specific
576 capabilities. It seems reasonable for now... */
577 zlog_warn ("%s Vendor specific capability %d",
578 peer->host, caphdr.code);
579 }
580 else
581 {
582 zlog_warn ("%s unrecognized capability code: %d - ignored",
583 peer->host, caphdr.code);
584 memcpy (*error, sp, caphdr.length + 2);
585 *error += caphdr.length + 2;
586 }
587 }
588 if (stream_get_getp(s) != (start + caphdr.length))
589 {
590 if (stream_get_getp(s) > (start + caphdr.length))
591 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
592 peer->host, LOOKUP (capcode_str, caphdr.code),
593 caphdr.length);
594 stream_set_getp (s, start + caphdr.length);
595 }
paul718e3742002-12-13 20:15:29 +0000596 }
597 return 0;
598}
599
paul94f2b392005-06-28 12:44:16 +0000600static int
Paul Jakma6d582722007-08-06 15:21:45 +0000601bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000602{
603 bgp_notify_send (peer,
604 BGP_NOTIFY_OPEN_ERR,
605 BGP_NOTIFY_OPEN_AUTH_FAILURE);
606 return -1;
607}
608
paul94f2b392005-06-28 12:44:16 +0000609static int
paul718e3742002-12-13 20:15:29 +0000610strict_capability_same (struct peer *peer)
611{
612 int i, j;
613
614 for (i = AFI_IP; i < AFI_MAX; i++)
615 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
616 if (peer->afc[i][j] != peer->afc_nego[i][j])
617 return 0;
618 return 1;
619}
620
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000621/* peek into option, stores ASN to *as4 if the AS4 capability was found.
622 * Returns 0 if no as4 found, as4cap value otherwise.
623 */
624as_t
625peek_for_as4_capability (struct peer *peer, u_char length)
626{
627 struct stream *s = BGP_INPUT (peer);
628 size_t orig_getp = stream_get_getp (s);
629 size_t end = orig_getp + length;
630 as_t as4 = 0;
631
632 /* The full capability parser will better flag the error.. */
633 if (STREAM_READABLE(s) < length)
634 return 0;
635
636 if (BGP_DEBUG (as4, AS4))
637 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
638 " peeking for as4",
639 peer->host, length);
640 /* the error cases we DONT handle, we ONLY try to read as4 out of
641 * correctly formatted options.
642 */
643 while (stream_get_getp(s) < end)
644 {
645 u_char opt_type;
646 u_char opt_length;
647
648 /* Check the length. */
649 if (stream_get_getp (s) + 2 > end)
650 goto end;
651
652 /* Fetch option type and length. */
653 opt_type = stream_getc (s);
654 opt_length = stream_getc (s);
655
656 /* Option length check. */
657 if (stream_get_getp (s) + opt_length > end)
658 goto end;
659
660 if (opt_type == BGP_OPEN_OPT_CAP)
661 {
662 unsigned long capd_start = stream_get_getp (s);
663 unsigned long capd_end = capd_start + opt_length;
664
665 assert (capd_end <= end);
666
667 while (stream_get_getp (s) < capd_end)
668 {
669 struct capability_header hdr;
670
671 if (stream_get_getp (s) + 2 > capd_end)
672 goto end;
673
674 hdr.code = stream_getc (s);
675 hdr.length = stream_getc (s);
676
677 if ((stream_get_getp(s) + hdr.length) > capd_end)
678 goto end;
679
680 if (hdr.code == CAPABILITY_CODE_AS4)
681 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000682 if (BGP_DEBUG (as4, AS4))
683 zlog_info ("[AS4] found AS4 capability, about to parse");
684 as4 = bgp_capability_as4 (peer, &hdr);
685
686 goto end;
687 }
688 stream_forward_getp (s, hdr.length);
689 }
690 }
691 }
692
693end:
694 stream_set_getp (s, orig_getp);
695 return as4;
696}
697
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800698/**
699 * Parse open option.
700 *
701 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
702 */
paul718e3742002-12-13 20:15:29 +0000703int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800704bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000705{
706 int ret;
paul718e3742002-12-13 20:15:29 +0000707 u_char *error;
708 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000709 struct stream *s = BGP_INPUT(peer);
710 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000711
712 ret = 0;
paul718e3742002-12-13 20:15:29 +0000713 error = error_data;
714
715 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000716 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000717 peer->host, length);
718
Paul Jakma6d582722007-08-06 15:21:45 +0000719 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000720 {
Paul Jakma6d582722007-08-06 15:21:45 +0000721 u_char opt_type;
722 u_char opt_length;
723
724 /* Must have at least an OPEN option header */
725 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000726 {
727 zlog_info ("%s Option length error", peer->host);
728 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
729 return -1;
730 }
731
732 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000733 opt_type = stream_getc (s);
734 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000735
736 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000737 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000738 {
739 zlog_info ("%s Option length error", peer->host);
740 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
741 return -1;
742 }
743
744 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000745 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000746 peer->host, opt_type,
747 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
748 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
749 opt_length);
750
751 switch (opt_type)
752 {
753 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000754 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000755 break;
756 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800757 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000758 break;
759 default:
760 bgp_notify_send (peer,
761 BGP_NOTIFY_OPEN_ERR,
762 BGP_NOTIFY_OPEN_UNSUP_PARAM);
763 ret = -1;
764 break;
765 }
766
767 /* Parse error. To accumulate all unsupported capability codes,
768 bgp_capability_parse does not return -1 when encounter
769 unsupported capability code. To detect that, please check
770 error and erro_data pointer, like below. */
771 if (ret < 0)
772 return -1;
paul718e3742002-12-13 20:15:29 +0000773 }
774
775 /* All OPEN option is parsed. Check capability when strict compare
776 flag is enabled.*/
777 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
778 {
779 /* If Unsupported Capability exists. */
780 if (error != error_data)
781 {
782 bgp_notify_send_with_data (peer,
783 BGP_NOTIFY_OPEN_ERR,
784 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
785 error_data, error - error_data);
786 return -1;
787 }
788
789 /* Check local capability does not negotiated with remote
790 peer. */
791 if (! strict_capability_same (peer))
792 {
793 bgp_notify_send (peer,
794 BGP_NOTIFY_OPEN_ERR,
795 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
796 return -1;
797 }
798 }
799
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800800 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000801 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800802 if (*mp_capability &&
803 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000804 {
805 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
806 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
807 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
808 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
809 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
810 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800811 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
812 "overlap with received MP capabilities",
813 peer->host);
paul718e3742002-12-13 20:15:29 +0000814
815 if (error != error_data)
816
817 bgp_notify_send_with_data (peer,
818 BGP_NOTIFY_OPEN_ERR,
819 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
820 error_data, error - error_data);
821 else
822 bgp_notify_send (peer,
823 BGP_NOTIFY_OPEN_ERR,
824 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
825 return -1;
826 }
827 }
828 return 0;
829}
830
paul94f2b392005-06-28 12:44:16 +0000831static void
paul718e3742002-12-13 20:15:29 +0000832bgp_open_capability_orf (struct stream *s, struct peer *peer,
833 afi_t afi, safi_t safi, u_char code)
834{
835 u_char cap_len;
836 u_char orf_len;
837 unsigned long capp;
838 unsigned long orfp;
839 unsigned long numberp;
840 int number_of_orfs = 0;
841
842 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400843 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000844
845 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000846 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000847 stream_putc (s, 0); /* Capability Length */
848 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000849 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000850 stream_putc (s, 0); /* ORF Length */
851 stream_putw (s, afi);
852 stream_putc (s, 0);
853 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000854 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000855 stream_putc (s, 0); /* Number of ORFs */
856
857 /* Address Prefix ORF */
858 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
859 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
860 {
861 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
862 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
863
864 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
865 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
866 {
867 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
868 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
869 stream_putc (s, ORF_MODE_BOTH);
870 }
871 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
872 {
873 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
874 stream_putc (s, ORF_MODE_SEND);
875 }
876 else
877 {
878 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
879 stream_putc (s, ORF_MODE_RECEIVE);
880 }
881 number_of_orfs++;
882 }
883
884 /* Total Number of ORFs. */
885 stream_putc_at (s, numberp, number_of_orfs);
886
887 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000888 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000889 stream_putc_at (s, orfp, orf_len);
890
891 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000892 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000893 stream_putc_at (s, capp, cap_len);
894}
895
896/* Fill in capability open option to the packet. */
897void
898bgp_open_capability (struct stream *s, struct peer *peer)
899{
900 u_char len;
901 unsigned long cp;
902 afi_t afi;
903 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000904 as_t local_as;
paul718e3742002-12-13 20:15:29 +0000905
906 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000907 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000908
909 /* Opt Parm Len. */
910 stream_putc (s, 0);
911
912 /* Do not send capability. */
913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
914 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
915 return;
916
paul718e3742002-12-13 20:15:29 +0000917 /* IPv4 unicast. */
918 if (peer->afc[AFI_IP][SAFI_UNICAST])
919 {
920 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
921 stream_putc (s, BGP_OPEN_OPT_CAP);
922 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
923 stream_putc (s, CAPABILITY_CODE_MP);
924 stream_putc (s, CAPABILITY_CODE_MP_LEN);
925 stream_putw (s, AFI_IP);
926 stream_putc (s, 0);
927 stream_putc (s, SAFI_UNICAST);
928 }
929 /* IPv4 multicast. */
930 if (peer->afc[AFI_IP][SAFI_MULTICAST])
931 {
932 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
933 stream_putc (s, BGP_OPEN_OPT_CAP);
934 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
935 stream_putc (s, CAPABILITY_CODE_MP);
936 stream_putc (s, CAPABILITY_CODE_MP_LEN);
937 stream_putw (s, AFI_IP);
938 stream_putc (s, 0);
939 stream_putc (s, SAFI_MULTICAST);
940 }
941 /* IPv4 VPN */
942 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
943 {
944 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
945 stream_putc (s, BGP_OPEN_OPT_CAP);
946 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
947 stream_putc (s, CAPABILITY_CODE_MP);
948 stream_putc (s, CAPABILITY_CODE_MP_LEN);
949 stream_putw (s, AFI_IP);
950 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400951 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000952 }
953#ifdef HAVE_IPV6
954 /* IPv6 unicast. */
955 if (peer->afc[AFI_IP6][SAFI_UNICAST])
956 {
957 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
958 stream_putc (s, BGP_OPEN_OPT_CAP);
959 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
960 stream_putc (s, CAPABILITY_CODE_MP);
961 stream_putc (s, CAPABILITY_CODE_MP_LEN);
962 stream_putw (s, AFI_IP6);
963 stream_putc (s, 0);
964 stream_putc (s, SAFI_UNICAST);
965 }
966 /* IPv6 multicast. */
967 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
968 {
969 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
970 stream_putc (s, BGP_OPEN_OPT_CAP);
971 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
972 stream_putc (s, CAPABILITY_CODE_MP);
973 stream_putc (s, CAPABILITY_CODE_MP_LEN);
974 stream_putw (s, AFI_IP6);
975 stream_putc (s, 0);
976 stream_putc (s, SAFI_MULTICAST);
977 }
978#endif /* HAVE_IPV6 */
979
980 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +0000981 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
982 stream_putc (s, BGP_OPEN_OPT_CAP);
983 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
984 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
985 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
986 stream_putc (s, BGP_OPEN_OPT_CAP);
987 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
988 stream_putc (s, CAPABILITY_CODE_REFRESH);
989 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +0000990
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000991 /* AS4 */
992 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
993 stream_putc (s, BGP_OPEN_OPT_CAP);
994 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
995 stream_putc (s, CAPABILITY_CODE_AS4);
996 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
997 if ( peer->change_local_as )
998 local_as = peer->change_local_as;
999 else
1000 local_as = peer->local_as;
1001 stream_putl (s, local_as );
1002
paul718e3742002-12-13 20:15:29 +00001003 /* ORF capability. */
1004 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1005 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1006 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1007 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1008 {
1009 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1010 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1011 }
1012
1013 /* Dynamic capability. */
1014 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1015 {
1016 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1017 stream_putc (s, BGP_OPEN_OPT_CAP);
1018 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1019 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1020 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1021 }
1022
hasso538621f2004-05-21 09:31:30 +00001023 /* Graceful restart capability */
1024 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1025 {
1026 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1027 stream_putc (s, BGP_OPEN_OPT_CAP);
1028 stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
1029 stream_putc (s, CAPABILITY_CODE_RESTART);
1030 stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
1031 stream_putw (s, peer->bgp->restart_time);
1032 }
1033
paul718e3742002-12-13 20:15:29 +00001034 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001035 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001036 stream_putc_at (s, cp, len);
1037}