blob: 727388283c7437b04105890b37a1b2f8e97578e6 [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);
Paul Jakma68ec4242015-11-25 17:14:34 +0000238 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
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);
Paul Jakma68ec4242015-11-25 17:14:34 +0000472 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000473 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);
Paul Jakma68ec4242015-11-25 17:14:34 +0000484 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000485 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 Jakma68ec4242015-11-25 17:14:34 +0000514 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
515 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma6d582722007-08-06 15:21:45 +0000516 return -1;
517 }
518 /* we deliberately ignore unknown codes, see below */
519 default:
520 break;
521 }
522
523 switch (caphdr.code)
524 {
525 case CAPABILITY_CODE_MP:
526 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800527 *mp_capability = 1;
528
Paul Jakma6d582722007-08-06 15:21:45 +0000529 /* Ignore capability when override-capability is set. */
530 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
531 {
532 /* Set negotiated value. */
533 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000534
Paul Jakma6d582722007-08-06 15:21:45 +0000535 /* Unsupported Capability. */
536 if (ret < 0)
537 {
538 /* Store return data. */
539 memcpy (*error, sp, caphdr.length + 2);
540 *error += caphdr.length + 2;
541 }
542 }
543 }
544 break;
545 case CAPABILITY_CODE_REFRESH:
546 case CAPABILITY_CODE_REFRESH_OLD:
547 {
548 /* BGP refresh capability */
549 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
550 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
551 else
552 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
553 }
554 break;
555 case CAPABILITY_CODE_ORF:
556 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400557 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000558 return -1;
559 break;
560 case CAPABILITY_CODE_RESTART:
561 if (bgp_capability_restart (peer, &caphdr))
562 return -1;
563 break;
564 case CAPABILITY_CODE_DYNAMIC:
565 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
566 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000567 case CAPABILITY_CODE_AS4:
568 /* Already handled as a special-case parsing of the capabilities
569 * at the beginning of OPEN processing. So we care not a jot
570 * for the value really, only error case.
571 */
572 if (!bgp_capability_as4 (peer, &caphdr))
573 return -1;
574 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000575 default:
576 if (caphdr.code > 128)
577 {
578 /* We don't send Notification for unknown vendor specific
579 capabilities. It seems reasonable for now... */
580 zlog_warn ("%s Vendor specific capability %d",
581 peer->host, caphdr.code);
582 }
583 else
584 {
585 zlog_warn ("%s unrecognized capability code: %d - ignored",
586 peer->host, caphdr.code);
587 memcpy (*error, sp, caphdr.length + 2);
588 *error += caphdr.length + 2;
589 }
590 }
591 if (stream_get_getp(s) != (start + caphdr.length))
592 {
593 if (stream_get_getp(s) > (start + caphdr.length))
594 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
595 peer->host, LOOKUP (capcode_str, caphdr.code),
596 caphdr.length);
597 stream_set_getp (s, start + caphdr.length);
598 }
paul718e3742002-12-13 20:15:29 +0000599 }
600 return 0;
601}
602
paul94f2b392005-06-28 12:44:16 +0000603static int
Paul Jakma6d582722007-08-06 15:21:45 +0000604bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000605{
606 bgp_notify_send (peer,
607 BGP_NOTIFY_OPEN_ERR,
608 BGP_NOTIFY_OPEN_AUTH_FAILURE);
609 return -1;
610}
611
paul94f2b392005-06-28 12:44:16 +0000612static int
paul718e3742002-12-13 20:15:29 +0000613strict_capability_same (struct peer *peer)
614{
615 int i, j;
616
617 for (i = AFI_IP; i < AFI_MAX; i++)
618 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
619 if (peer->afc[i][j] != peer->afc_nego[i][j])
620 return 0;
621 return 1;
622}
623
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000624/* peek into option, stores ASN to *as4 if the AS4 capability was found.
625 * Returns 0 if no as4 found, as4cap value otherwise.
626 */
627as_t
628peek_for_as4_capability (struct peer *peer, u_char length)
629{
630 struct stream *s = BGP_INPUT (peer);
631 size_t orig_getp = stream_get_getp (s);
632 size_t end = orig_getp + length;
633 as_t as4 = 0;
634
635 /* The full capability parser will better flag the error.. */
636 if (STREAM_READABLE(s) < length)
637 return 0;
638
639 if (BGP_DEBUG (as4, AS4))
640 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
641 " peeking for as4",
642 peer->host, length);
643 /* the error cases we DONT handle, we ONLY try to read as4 out of
644 * correctly formatted options.
645 */
646 while (stream_get_getp(s) < end)
647 {
648 u_char opt_type;
649 u_char opt_length;
650
651 /* Check the length. */
652 if (stream_get_getp (s) + 2 > end)
653 goto end;
654
655 /* Fetch option type and length. */
656 opt_type = stream_getc (s);
657 opt_length = stream_getc (s);
658
659 /* Option length check. */
660 if (stream_get_getp (s) + opt_length > end)
661 goto end;
662
663 if (opt_type == BGP_OPEN_OPT_CAP)
664 {
665 unsigned long capd_start = stream_get_getp (s);
666 unsigned long capd_end = capd_start + opt_length;
667
668 assert (capd_end <= end);
669
670 while (stream_get_getp (s) < capd_end)
671 {
672 struct capability_header hdr;
673
674 if (stream_get_getp (s) + 2 > capd_end)
675 goto end;
676
677 hdr.code = stream_getc (s);
678 hdr.length = stream_getc (s);
679
680 if ((stream_get_getp(s) + hdr.length) > capd_end)
681 goto end;
682
683 if (hdr.code == CAPABILITY_CODE_AS4)
684 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000685 if (BGP_DEBUG (as4, AS4))
686 zlog_info ("[AS4] found AS4 capability, about to parse");
687 as4 = bgp_capability_as4 (peer, &hdr);
688
689 goto end;
690 }
691 stream_forward_getp (s, hdr.length);
692 }
693 }
694 }
695
696end:
697 stream_set_getp (s, orig_getp);
698 return as4;
699}
700
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800701/**
702 * Parse open option.
703 *
704 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
705 */
paul718e3742002-12-13 20:15:29 +0000706int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800707bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000708{
709 int ret;
paul718e3742002-12-13 20:15:29 +0000710 u_char *error;
711 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000712 struct stream *s = BGP_INPUT(peer);
713 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000714
715 ret = 0;
paul718e3742002-12-13 20:15:29 +0000716 error = error_data;
717
718 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000719 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000720 peer->host, length);
721
Paul Jakma6d582722007-08-06 15:21:45 +0000722 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000723 {
Paul Jakma6d582722007-08-06 15:21:45 +0000724 u_char opt_type;
725 u_char opt_length;
726
727 /* Must have at least an OPEN option header */
728 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000729 {
730 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000731 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
732 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000733 return -1;
734 }
735
736 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000737 opt_type = stream_getc (s);
738 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000739
740 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000741 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000742 {
743 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000744 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
745 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000746 return -1;
747 }
748
749 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000750 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000751 peer->host, opt_type,
752 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
753 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
754 opt_length);
755
756 switch (opt_type)
757 {
758 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000759 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000760 break;
761 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800762 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000763 break;
764 default:
765 bgp_notify_send (peer,
766 BGP_NOTIFY_OPEN_ERR,
767 BGP_NOTIFY_OPEN_UNSUP_PARAM);
768 ret = -1;
769 break;
770 }
771
772 /* Parse error. To accumulate all unsupported capability codes,
773 bgp_capability_parse does not return -1 when encounter
774 unsupported capability code. To detect that, please check
775 error and erro_data pointer, like below. */
776 if (ret < 0)
777 return -1;
paul718e3742002-12-13 20:15:29 +0000778 }
779
780 /* All OPEN option is parsed. Check capability when strict compare
781 flag is enabled.*/
782 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
783 {
784 /* If Unsupported Capability exists. */
785 if (error != error_data)
786 {
787 bgp_notify_send_with_data (peer,
788 BGP_NOTIFY_OPEN_ERR,
789 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
790 error_data, error - error_data);
791 return -1;
792 }
793
794 /* Check local capability does not negotiated with remote
795 peer. */
796 if (! strict_capability_same (peer))
797 {
798 bgp_notify_send (peer,
799 BGP_NOTIFY_OPEN_ERR,
800 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
801 return -1;
802 }
803 }
804
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800805 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000806 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800807 if (*mp_capability &&
808 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000809 {
810 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
811 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
812 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
813 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
814 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
815 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800816 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
817 "overlap with received MP capabilities",
818 peer->host);
paul718e3742002-12-13 20:15:29 +0000819
820 if (error != error_data)
821
822 bgp_notify_send_with_data (peer,
823 BGP_NOTIFY_OPEN_ERR,
824 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
825 error_data, error - error_data);
826 else
827 bgp_notify_send (peer,
828 BGP_NOTIFY_OPEN_ERR,
829 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
830 return -1;
831 }
832 }
833 return 0;
834}
835
paul94f2b392005-06-28 12:44:16 +0000836static void
paul718e3742002-12-13 20:15:29 +0000837bgp_open_capability_orf (struct stream *s, struct peer *peer,
838 afi_t afi, safi_t safi, u_char code)
839{
840 u_char cap_len;
841 u_char orf_len;
842 unsigned long capp;
843 unsigned long orfp;
844 unsigned long numberp;
845 int number_of_orfs = 0;
846
847 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400848 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000849
850 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000851 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000852 stream_putc (s, 0); /* Capability Length */
853 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000854 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000855 stream_putc (s, 0); /* ORF Length */
856 stream_putw (s, afi);
857 stream_putc (s, 0);
858 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000859 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000860 stream_putc (s, 0); /* Number of ORFs */
861
862 /* Address Prefix ORF */
863 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
864 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
865 {
866 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
867 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
868
869 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
870 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
871 {
872 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
873 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
874 stream_putc (s, ORF_MODE_BOTH);
875 }
876 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
877 {
878 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
879 stream_putc (s, ORF_MODE_SEND);
880 }
881 else
882 {
883 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
884 stream_putc (s, ORF_MODE_RECEIVE);
885 }
886 number_of_orfs++;
887 }
888
889 /* Total Number of ORFs. */
890 stream_putc_at (s, numberp, number_of_orfs);
891
892 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000893 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000894 stream_putc_at (s, orfp, orf_len);
895
896 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000897 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000898 stream_putc_at (s, capp, cap_len);
899}
900
901/* Fill in capability open option to the packet. */
902void
903bgp_open_capability (struct stream *s, struct peer *peer)
904{
905 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700906 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000907 afi_t afi;
908 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000909 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700910 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000911
912 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000913 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000914
915 /* Opt Parm Len. */
916 stream_putc (s, 0);
917
918 /* Do not send capability. */
919 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
920 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
921 return;
922
paul718e3742002-12-13 20:15:29 +0000923 /* IPv4 unicast. */
924 if (peer->afc[AFI_IP][SAFI_UNICAST])
925 {
926 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
927 stream_putc (s, BGP_OPEN_OPT_CAP);
928 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
929 stream_putc (s, CAPABILITY_CODE_MP);
930 stream_putc (s, CAPABILITY_CODE_MP_LEN);
931 stream_putw (s, AFI_IP);
932 stream_putc (s, 0);
933 stream_putc (s, SAFI_UNICAST);
934 }
935 /* IPv4 multicast. */
936 if (peer->afc[AFI_IP][SAFI_MULTICAST])
937 {
938 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
939 stream_putc (s, BGP_OPEN_OPT_CAP);
940 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
941 stream_putc (s, CAPABILITY_CODE_MP);
942 stream_putc (s, CAPABILITY_CODE_MP_LEN);
943 stream_putw (s, AFI_IP);
944 stream_putc (s, 0);
945 stream_putc (s, SAFI_MULTICAST);
946 }
947 /* IPv4 VPN */
948 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
949 {
950 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
951 stream_putc (s, BGP_OPEN_OPT_CAP);
952 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
953 stream_putc (s, CAPABILITY_CODE_MP);
954 stream_putc (s, CAPABILITY_CODE_MP_LEN);
955 stream_putw (s, AFI_IP);
956 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400957 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000958 }
959#ifdef HAVE_IPV6
960 /* IPv6 unicast. */
961 if (peer->afc[AFI_IP6][SAFI_UNICAST])
962 {
963 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
964 stream_putc (s, BGP_OPEN_OPT_CAP);
965 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
966 stream_putc (s, CAPABILITY_CODE_MP);
967 stream_putc (s, CAPABILITY_CODE_MP_LEN);
968 stream_putw (s, AFI_IP6);
969 stream_putc (s, 0);
970 stream_putc (s, SAFI_UNICAST);
971 }
972 /* IPv6 multicast. */
973 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
974 {
975 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
976 stream_putc (s, BGP_OPEN_OPT_CAP);
977 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
978 stream_putc (s, CAPABILITY_CODE_MP);
979 stream_putc (s, CAPABILITY_CODE_MP_LEN);
980 stream_putw (s, AFI_IP6);
981 stream_putc (s, 0);
982 stream_putc (s, SAFI_MULTICAST);
983 }
984#endif /* HAVE_IPV6 */
985
986 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +0000987 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
988 stream_putc (s, BGP_OPEN_OPT_CAP);
989 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
990 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
991 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
992 stream_putc (s, BGP_OPEN_OPT_CAP);
993 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
994 stream_putc (s, CAPABILITY_CODE_REFRESH);
995 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +0000996
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000997 /* AS4 */
998 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
999 stream_putc (s, BGP_OPEN_OPT_CAP);
1000 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1001 stream_putc (s, CAPABILITY_CODE_AS4);
1002 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1003 if ( peer->change_local_as )
1004 local_as = peer->change_local_as;
1005 else
1006 local_as = peer->local_as;
1007 stream_putl (s, local_as );
1008
paul718e3742002-12-13 20:15:29 +00001009 /* ORF capability. */
1010 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1011 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1012 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1013 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1014 {
1015 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1016 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1017 }
1018
1019 /* Dynamic capability. */
1020 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1021 {
1022 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1023 stream_putc (s, BGP_OPEN_OPT_CAP);
1024 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1025 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1026 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1027 }
1028
Vipin Kumardd49eb12014-09-30 14:36:38 -07001029 /* Sending base graceful-restart capability irrespective of the config */
1030 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1031 stream_putc (s, BGP_OPEN_OPT_CAP);
1032 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1033 stream_putc (s, 0); /* Capability Length */
1034 stream_putc (s, CAPABILITY_CODE_RESTART);
1035 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1036 stream_putc (s, 0);
1037 restart_time = peer->bgp->restart_time;
1038 if (peer->bgp->t_startup)
1039 {
1040 SET_FLAG (restart_time, RESTART_R_BIT);
1041 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1042 }
1043 stream_putw (s, restart_time);
1044
1045 /* Send address-family specific graceful-restart capability only when GR config
1046 is present */
hasso538621f2004-05-21 09:31:30 +00001047 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1048 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001049 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1050 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1051 if (peer->afc[afi][safi])
1052 {
1053 stream_putw (s, afi);
1054 stream_putc (s, safi);
1055 stream_putc (s, 0); //Forwarding is not retained as of now.
1056 }
1057 }
1058
1059 /* Total Graceful restart capability Len. */
1060 len = stream_get_endp (s) - rcapp - 1;
1061 stream_putc_at (s, rcapp, len);
1062
1063 /* Total Capability Len. */
1064 len = stream_get_endp (s) - capp - 1;
1065 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001066
paul718e3742002-12-13 20:15:29 +00001067 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001068 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001069 stream_putc_at (s, cp, len);
1070}