blob: b9d6e93f3335b4bf5edb751e4c3bc97329693de5 [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 */
David Lamparter5e728e92013-01-23 05:50:24 +0100233 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;
Paul Jakma6d582722007-08-06 15:21:45 +0000341 size_t end = stream_get_getp (s) + caphdr->length;
342
343 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
344 restart_flag_time = stream_getw(s);
345 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
Paul Jakmaec98d902014-10-14 11:14:06 +0100346 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
347
Paul Jakma6d582722007-08-06 15:21:45 +0000348 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",
Paul Jakmaec98d902014-10-14 11:14:06 +0100355 peer->host,
356 CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " "
357 : " not ",
Paul Jakma6d582722007-08-06 15:21:45 +0000358 peer->v_gr_restart);
359 }
360
Peter Pentchev21cc7692011-09-12 16:30:31 +0400361 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000362 {
363 afi_t afi = stream_getw (s);
364 safi_t safi = stream_getc (s);
365 u_char flag = stream_getc (s);
366
367 if (!bgp_afi_safi_valid_indices (afi, &safi))
368 {
369 if (BGP_DEBUG (normal, NORMAL))
370 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
371 " Ignore the Graceful Restart capability",
372 peer->host, afi, safi);
373 }
374 else if (!peer->afc[afi][safi])
375 {
376 if (BGP_DEBUG (normal, NORMAL))
377 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
378 " Ignore the Graceful Restart capability",
379 peer->host, afi, safi);
380 }
381 else
382 {
383 if (BGP_DEBUG (normal, NORMAL))
384 zlog_debug ("%s Address family %s is%spreserved", peer->host,
385 afi_safi_print (afi, safi),
386 CHECK_FLAG (peer->af_cap[afi][safi],
387 PEER_CAP_RESTART_AF_PRESERVE_RCV)
388 ? " " : " not ");
389
390 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
391 if (CHECK_FLAG (flag, RESTART_F_BIT))
392 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
393
394 }
395 }
396 return 0;
397}
398
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000399static as_t
400bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
401{
Paul Jakma58617392012-01-09 20:59:26 +0000402 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
403
404 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
405 {
406 zlog_err ("%s AS4 capability has incorrect data length %d",
407 peer->host, hdr->length);
408 return 0;
409 }
410
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000411 as_t as4 = stream_getl (BGP_INPUT(peer));
412
413 if (BGP_DEBUG (as4, AS4))
414 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
415 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000416 return as4;
417}
418
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700419static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000420{
Paul Jakma6d582722007-08-06 15:21:45 +0000421 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
422 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
423 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
424 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
425 { CAPABILITY_CODE_AS4, "4-octet AS number" },
426 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
427 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
428 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
429};
Balaji.G837d16c2012-09-26 14:09:10 +0530430static const int capcode_str_max = array_size(capcode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000431
432/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700433static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000434{
435 [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
436 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
437 [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
Paul Jakma370b64a2007-12-22 16:49:52 +0000438 [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
Paul Jakma6d582722007-08-06 15:21:45 +0000439 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
440 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
441 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
442 [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
443};
444
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800445/**
446 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000447 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800448 *
449 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
450 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000451 */
452static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800453bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
454 u_char **error)
paul718e3742002-12-13 20:15:29 +0000455{
456 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000457 struct stream *s = BGP_INPUT (peer);
458 size_t end = stream_get_getp (s) + length;
459
460 assert (STREAM_READABLE (s) >= length);
461
462 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000463 {
Paul Jakma6d582722007-08-06 15:21:45 +0000464 size_t start;
465 u_char *sp = stream_pnt (s);
466 struct capability_header caphdr;
467
paul718e3742002-12-13 20:15:29 +0000468 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000469 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000470 {
Paul Jakma6d582722007-08-06 15:21:45 +0000471 zlog_info ("%s Capability length error (< header)", peer->host);
paul718e3742002-12-13 20:15:29 +0000472 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
473 return -1;
474 }
Paul Jakma6d582722007-08-06 15:21:45 +0000475
476 caphdr.code = stream_getc (s);
477 caphdr.length = stream_getc (s);
478 start = stream_get_getp (s);
479
480 /* Capability length check sanity check. */
481 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000482 {
Paul Jakma6d582722007-08-06 15:21:45 +0000483 zlog_info ("%s Capability length error (< length)", peer->host);
paul718e3742002-12-13 20:15:29 +0000484 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
485 return -1;
486 }
Paul Jakma6d582722007-08-06 15:21:45 +0000487
488 if (BGP_DEBUG (normal, NORMAL))
489 zlog_debug ("%s OPEN has %s capability (%u), length %u",
490 peer->host,
491 LOOKUP (capcode_str, caphdr.code),
492 caphdr.code, caphdr.length);
493
494 /* Length sanity check, type-specific, for known capabilities */
495 switch (caphdr.code)
496 {
497 case CAPABILITY_CODE_MP:
498 case CAPABILITY_CODE_REFRESH:
499 case CAPABILITY_CODE_REFRESH_OLD:
500 case CAPABILITY_CODE_ORF:
501 case CAPABILITY_CODE_ORF_OLD:
502 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000503 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000504 case CAPABILITY_CODE_DYNAMIC:
505 /* Check length. */
506 if (caphdr.length < cap_minsizes[caphdr.code])
507 {
508 zlog_info ("%s %s Capability length error: got %u,"
509 " expected at least %u",
510 peer->host,
511 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700512 caphdr.length,
513 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma6d582722007-08-06 15:21:45 +0000514 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
515 return -1;
516 }
517 /* we deliberately ignore unknown codes, see below */
518 default:
519 break;
520 }
521
522 switch (caphdr.code)
523 {
524 case CAPABILITY_CODE_MP:
525 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800526 *mp_capability = 1;
527
Paul Jakma6d582722007-08-06 15:21:45 +0000528 /* Ignore capability when override-capability is set. */
529 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
530 {
531 /* Set negotiated value. */
532 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000533
Paul Jakma6d582722007-08-06 15:21:45 +0000534 /* Unsupported Capability. */
535 if (ret < 0)
536 {
537 /* Store return data. */
538 memcpy (*error, sp, caphdr.length + 2);
539 *error += caphdr.length + 2;
540 }
541 }
542 }
543 break;
544 case CAPABILITY_CODE_REFRESH:
545 case CAPABILITY_CODE_REFRESH_OLD:
546 {
547 /* BGP refresh capability */
548 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
549 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
550 else
551 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
552 }
553 break;
554 case CAPABILITY_CODE_ORF:
555 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400556 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000557 return -1;
558 break;
559 case CAPABILITY_CODE_RESTART:
560 if (bgp_capability_restart (peer, &caphdr))
561 return -1;
562 break;
563 case CAPABILITY_CODE_DYNAMIC:
564 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
565 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000566 case CAPABILITY_CODE_AS4:
567 /* Already handled as a special-case parsing of the capabilities
568 * at the beginning of OPEN processing. So we care not a jot
569 * for the value really, only error case.
570 */
571 if (!bgp_capability_as4 (peer, &caphdr))
572 return -1;
573 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000574 default:
575 if (caphdr.code > 128)
576 {
577 /* We don't send Notification for unknown vendor specific
578 capabilities. It seems reasonable for now... */
579 zlog_warn ("%s Vendor specific capability %d",
580 peer->host, caphdr.code);
581 }
582 else
583 {
584 zlog_warn ("%s unrecognized capability code: %d - ignored",
585 peer->host, caphdr.code);
586 memcpy (*error, sp, caphdr.length + 2);
587 *error += caphdr.length + 2;
588 }
589 }
590 if (stream_get_getp(s) != (start + caphdr.length))
591 {
592 if (stream_get_getp(s) > (start + caphdr.length))
593 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
594 peer->host, LOOKUP (capcode_str, caphdr.code),
595 caphdr.length);
596 stream_set_getp (s, start + caphdr.length);
597 }
paul718e3742002-12-13 20:15:29 +0000598 }
599 return 0;
600}
601
paul94f2b392005-06-28 12:44:16 +0000602static int
Paul Jakma6d582722007-08-06 15:21:45 +0000603bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000604{
605 bgp_notify_send (peer,
606 BGP_NOTIFY_OPEN_ERR,
607 BGP_NOTIFY_OPEN_AUTH_FAILURE);
608 return -1;
609}
610
paul94f2b392005-06-28 12:44:16 +0000611static int
paul718e3742002-12-13 20:15:29 +0000612strict_capability_same (struct peer *peer)
613{
614 int i, j;
615
616 for (i = AFI_IP; i < AFI_MAX; i++)
617 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
618 if (peer->afc[i][j] != peer->afc_nego[i][j])
619 return 0;
620 return 1;
621}
622
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000623/* peek into option, stores ASN to *as4 if the AS4 capability was found.
624 * Returns 0 if no as4 found, as4cap value otherwise.
625 */
626as_t
627peek_for_as4_capability (struct peer *peer, u_char length)
628{
629 struct stream *s = BGP_INPUT (peer);
630 size_t orig_getp = stream_get_getp (s);
631 size_t end = orig_getp + length;
632 as_t as4 = 0;
633
634 /* The full capability parser will better flag the error.. */
635 if (STREAM_READABLE(s) < length)
636 return 0;
637
638 if (BGP_DEBUG (as4, AS4))
639 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
640 " peeking for as4",
641 peer->host, length);
642 /* the error cases we DONT handle, we ONLY try to read as4 out of
643 * correctly formatted options.
644 */
645 while (stream_get_getp(s) < end)
646 {
647 u_char opt_type;
648 u_char opt_length;
649
650 /* Check the length. */
651 if (stream_get_getp (s) + 2 > end)
652 goto end;
653
654 /* Fetch option type and length. */
655 opt_type = stream_getc (s);
656 opt_length = stream_getc (s);
657
658 /* Option length check. */
659 if (stream_get_getp (s) + opt_length > end)
660 goto end;
661
662 if (opt_type == BGP_OPEN_OPT_CAP)
663 {
664 unsigned long capd_start = stream_get_getp (s);
665 unsigned long capd_end = capd_start + opt_length;
666
667 assert (capd_end <= end);
668
669 while (stream_get_getp (s) < capd_end)
670 {
671 struct capability_header hdr;
672
673 if (stream_get_getp (s) + 2 > capd_end)
674 goto end;
675
676 hdr.code = stream_getc (s);
677 hdr.length = stream_getc (s);
678
679 if ((stream_get_getp(s) + hdr.length) > capd_end)
680 goto end;
681
682 if (hdr.code == CAPABILITY_CODE_AS4)
683 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000684 if (BGP_DEBUG (as4, AS4))
685 zlog_info ("[AS4] found AS4 capability, about to parse");
686 as4 = bgp_capability_as4 (peer, &hdr);
687
688 goto end;
689 }
690 stream_forward_getp (s, hdr.length);
691 }
692 }
693 }
694
695end:
696 stream_set_getp (s, orig_getp);
697 return as4;
698}
699
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800700/**
701 * Parse open option.
702 *
703 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
704 */
paul718e3742002-12-13 20:15:29 +0000705int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800706bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000707{
708 int ret;
paul718e3742002-12-13 20:15:29 +0000709 u_char *error;
710 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000711 struct stream *s = BGP_INPUT(peer);
712 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000713
714 ret = 0;
paul718e3742002-12-13 20:15:29 +0000715 error = error_data;
716
717 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000718 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000719 peer->host, length);
720
Paul Jakma6d582722007-08-06 15:21:45 +0000721 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000722 {
Paul Jakma6d582722007-08-06 15:21:45 +0000723 u_char opt_type;
724 u_char opt_length;
725
726 /* Must have at least an OPEN option header */
727 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000728 {
729 zlog_info ("%s Option length error", peer->host);
730 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
731 return -1;
732 }
733
734 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000735 opt_type = stream_getc (s);
736 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000737
738 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000739 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000740 {
741 zlog_info ("%s Option length error", peer->host);
742 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
743 return -1;
744 }
745
746 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000747 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000748 peer->host, opt_type,
749 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
750 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
751 opt_length);
752
753 switch (opt_type)
754 {
755 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000756 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000757 break;
758 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800759 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000760 break;
761 default:
762 bgp_notify_send (peer,
763 BGP_NOTIFY_OPEN_ERR,
764 BGP_NOTIFY_OPEN_UNSUP_PARAM);
765 ret = -1;
766 break;
767 }
768
769 /* Parse error. To accumulate all unsupported capability codes,
770 bgp_capability_parse does not return -1 when encounter
771 unsupported capability code. To detect that, please check
772 error and erro_data pointer, like below. */
773 if (ret < 0)
774 return -1;
paul718e3742002-12-13 20:15:29 +0000775 }
776
777 /* All OPEN option is parsed. Check capability when strict compare
778 flag is enabled.*/
779 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
780 {
781 /* If Unsupported Capability exists. */
782 if (error != error_data)
783 {
784 bgp_notify_send_with_data (peer,
785 BGP_NOTIFY_OPEN_ERR,
786 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
787 error_data, error - error_data);
788 return -1;
789 }
790
791 /* Check local capability does not negotiated with remote
792 peer. */
793 if (! strict_capability_same (peer))
794 {
795 bgp_notify_send (peer,
796 BGP_NOTIFY_OPEN_ERR,
797 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
798 return -1;
799 }
800 }
801
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800802 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000803 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800804 if (*mp_capability &&
805 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000806 {
807 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
808 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
809 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
810 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
811 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
812 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800813 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
814 "overlap with received MP capabilities",
815 peer->host);
paul718e3742002-12-13 20:15:29 +0000816
817 if (error != error_data)
818
819 bgp_notify_send_with_data (peer,
820 BGP_NOTIFY_OPEN_ERR,
821 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
822 error_data, error - error_data);
823 else
824 bgp_notify_send (peer,
825 BGP_NOTIFY_OPEN_ERR,
826 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
827 return -1;
828 }
829 }
830 return 0;
831}
832
paul94f2b392005-06-28 12:44:16 +0000833static void
paul718e3742002-12-13 20:15:29 +0000834bgp_open_capability_orf (struct stream *s, struct peer *peer,
835 afi_t afi, safi_t safi, u_char code)
836{
837 u_char cap_len;
838 u_char orf_len;
839 unsigned long capp;
840 unsigned long orfp;
841 unsigned long numberp;
842 int number_of_orfs = 0;
843
844 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400845 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000846
847 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000848 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000849 stream_putc (s, 0); /* Capability Length */
850 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000851 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000852 stream_putc (s, 0); /* ORF Length */
853 stream_putw (s, afi);
854 stream_putc (s, 0);
855 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000856 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000857 stream_putc (s, 0); /* Number of ORFs */
858
859 /* Address Prefix ORF */
860 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
861 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
862 {
863 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
864 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
865
866 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
867 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
868 {
869 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
870 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
871 stream_putc (s, ORF_MODE_BOTH);
872 }
873 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
874 {
875 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
876 stream_putc (s, ORF_MODE_SEND);
877 }
878 else
879 {
880 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
881 stream_putc (s, ORF_MODE_RECEIVE);
882 }
883 number_of_orfs++;
884 }
885
886 /* Total Number of ORFs. */
887 stream_putc_at (s, numberp, number_of_orfs);
888
889 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000890 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000891 stream_putc_at (s, orfp, orf_len);
892
893 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000894 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000895 stream_putc_at (s, capp, cap_len);
896}
897
898/* Fill in capability open option to the packet. */
899void
900bgp_open_capability (struct stream *s, struct peer *peer)
901{
902 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700903 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000904 afi_t afi;
905 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000906 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700907 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000908
909 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000910 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000911
912 /* Opt Parm Len. */
913 stream_putc (s, 0);
914
915 /* Do not send capability. */
916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
917 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
918 return;
919
paul718e3742002-12-13 20:15:29 +0000920 /* IPv4 unicast. */
921 if (peer->afc[AFI_IP][SAFI_UNICAST])
922 {
923 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
924 stream_putc (s, BGP_OPEN_OPT_CAP);
925 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
926 stream_putc (s, CAPABILITY_CODE_MP);
927 stream_putc (s, CAPABILITY_CODE_MP_LEN);
928 stream_putw (s, AFI_IP);
929 stream_putc (s, 0);
930 stream_putc (s, SAFI_UNICAST);
931 }
932 /* IPv4 multicast. */
933 if (peer->afc[AFI_IP][SAFI_MULTICAST])
934 {
935 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
936 stream_putc (s, BGP_OPEN_OPT_CAP);
937 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
938 stream_putc (s, CAPABILITY_CODE_MP);
939 stream_putc (s, CAPABILITY_CODE_MP_LEN);
940 stream_putw (s, AFI_IP);
941 stream_putc (s, 0);
942 stream_putc (s, SAFI_MULTICAST);
943 }
944 /* IPv4 VPN */
945 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
946 {
947 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
948 stream_putc (s, BGP_OPEN_OPT_CAP);
949 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
950 stream_putc (s, CAPABILITY_CODE_MP);
951 stream_putc (s, CAPABILITY_CODE_MP_LEN);
952 stream_putw (s, AFI_IP);
953 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400954 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000955 }
956#ifdef HAVE_IPV6
957 /* IPv6 unicast. */
958 if (peer->afc[AFI_IP6][SAFI_UNICAST])
959 {
960 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
961 stream_putc (s, BGP_OPEN_OPT_CAP);
962 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
963 stream_putc (s, CAPABILITY_CODE_MP);
964 stream_putc (s, CAPABILITY_CODE_MP_LEN);
965 stream_putw (s, AFI_IP6);
966 stream_putc (s, 0);
967 stream_putc (s, SAFI_UNICAST);
968 }
969 /* IPv6 multicast. */
970 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
971 {
972 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
973 stream_putc (s, BGP_OPEN_OPT_CAP);
974 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
975 stream_putc (s, CAPABILITY_CODE_MP);
976 stream_putc (s, CAPABILITY_CODE_MP_LEN);
977 stream_putw (s, AFI_IP6);
978 stream_putc (s, 0);
979 stream_putc (s, SAFI_MULTICAST);
980 }
981#endif /* HAVE_IPV6 */
982
983 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +0000984 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
985 stream_putc (s, BGP_OPEN_OPT_CAP);
986 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
987 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
988 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
989 stream_putc (s, BGP_OPEN_OPT_CAP);
990 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
991 stream_putc (s, CAPABILITY_CODE_REFRESH);
992 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +0000993
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000994 /* AS4 */
995 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
996 stream_putc (s, BGP_OPEN_OPT_CAP);
997 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
998 stream_putc (s, CAPABILITY_CODE_AS4);
999 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1000 if ( peer->change_local_as )
1001 local_as = peer->change_local_as;
1002 else
1003 local_as = peer->local_as;
1004 stream_putl (s, local_as );
1005
paul718e3742002-12-13 20:15:29 +00001006 /* ORF capability. */
1007 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1008 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1009 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1010 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1011 {
1012 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1013 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1014 }
1015
1016 /* Dynamic capability. */
1017 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1018 {
1019 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1020 stream_putc (s, BGP_OPEN_OPT_CAP);
1021 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1022 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1023 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1024 }
1025
Vipin Kumardd49eb12014-09-30 14:36:38 -07001026 /* Sending base graceful-restart capability irrespective of the config */
1027 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1028 stream_putc (s, BGP_OPEN_OPT_CAP);
1029 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1030 stream_putc (s, 0); /* Capability Length */
1031 stream_putc (s, CAPABILITY_CODE_RESTART);
1032 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1033 stream_putc (s, 0);
1034 restart_time = peer->bgp->restart_time;
1035 if (peer->bgp->t_startup)
1036 {
1037 SET_FLAG (restart_time, RESTART_R_BIT);
1038 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1039 }
1040 stream_putw (s, restart_time);
1041
1042 /* Send address-family specific graceful-restart capability only when GR config
1043 is present */
hasso538621f2004-05-21 09:31:30 +00001044 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1045 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001046 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1047 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1048 if (peer->afc[afi][safi])
1049 {
1050 stream_putw (s, afi);
1051 stream_putc (s, safi);
1052 stream_putc (s, 0); //Forwarding is not retained as of now.
1053 }
1054 }
1055
1056 /* Total Graceful restart capability Len. */
1057 len = stream_get_endp (s) - rcapp - 1;
1058 stream_putc_at (s, rcapp, len);
1059
1060 /* Total Capability Len. */
1061 len = stream_get_endp (s) - capp - 1;
1062 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001063
paul718e3742002-12-13 20:15:29 +00001064 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001065 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001066 stream_putc_at (s, cp, len);
1067}