blob: 38d9dc56c2be1847a2c2f16efa231760bc316819 [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 {
Donald Sharpf3cfc462016-01-07 09:33:28 -0500129 case AFI_IP:
130 case AFI_IP6:
131 switch (*safi)
132 {
133 /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
134 case SAFI_MPLS_LABELED_VPN:
135 *safi = SAFI_MPLS_VPN;
136 case SAFI_UNICAST:
137 case SAFI_MULTICAST:
138 case SAFI_MPLS_VPN:
139 return 1;
140 }
141 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000142 }
Donald Sharpf3cfc462016-01-07 09:33:28 -0500143
Paul Jakma6d582722007-08-06 15:21:45 +0000144 zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
Donald Sharpf3cfc462016-01-07 09:33:28 -0500145
Paul Jakma6d582722007-08-06 15:21:45 +0000146 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 */
Donald Sharpf3cfc462016-01-07 09:33:28 -0500233 if (CAPABILITY_CODE_ORF_LEN + (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{
Donald Sharpf3cfc462016-01-07 09:33:28 -0500435 [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000436 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500437 [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
438 [CAPABILITY_CODE_RESTART] = 6,
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,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500442 [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000443};
444
Paul Jakma4078f2e2015-11-25 17:14:35 +0000445/* value the capability must be a multiple of.
446 * 0-data capabilities won't be checked against this.
447 * Other capabilities whose data doesn't fall on convenient boundaries for this
448 * table should be set to 1.
449 */
450static const size_t cap_modsizes[] =
451{
452 [CAPABILITY_CODE_MP] = 4,
453 [CAPABILITY_CODE_REFRESH] = 1,
454 [CAPABILITY_CODE_ORF] = 1,
455 [CAPABILITY_CODE_RESTART] = 1,
456 [CAPABILITY_CODE_AS4] = 4,
457 [CAPABILITY_CODE_DYNAMIC] = 1,
458 [CAPABILITY_CODE_REFRESH_OLD] = 1,
459 [CAPABILITY_CODE_ORF_OLD] = 1,
460};
461
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800462/**
463 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000464 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800465 *
466 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
467 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000468 */
469static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800470bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
471 u_char **error)
paul718e3742002-12-13 20:15:29 +0000472{
473 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000474 struct stream *s = BGP_INPUT (peer);
475 size_t end = stream_get_getp (s) + length;
476
477 assert (STREAM_READABLE (s) >= length);
478
479 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000480 {
Paul Jakma6d582722007-08-06 15:21:45 +0000481 size_t start;
482 u_char *sp = stream_pnt (s);
483 struct capability_header caphdr;
484
paul718e3742002-12-13 20:15:29 +0000485 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000486 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000487 {
Paul Jakma6d582722007-08-06 15:21:45 +0000488 zlog_info ("%s Capability length error (< header)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000489 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000490 return -1;
491 }
Paul Jakma6d582722007-08-06 15:21:45 +0000492
493 caphdr.code = stream_getc (s);
494 caphdr.length = stream_getc (s);
495 start = stream_get_getp (s);
496
497 /* Capability length check sanity check. */
498 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000499 {
Paul Jakma6d582722007-08-06 15:21:45 +0000500 zlog_info ("%s Capability length error (< length)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000501 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000502 return -1;
503 }
Paul Jakma6d582722007-08-06 15:21:45 +0000504
505 if (BGP_DEBUG (normal, NORMAL))
506 zlog_debug ("%s OPEN has %s capability (%u), length %u",
507 peer->host,
508 LOOKUP (capcode_str, caphdr.code),
509 caphdr.code, caphdr.length);
510
511 /* Length sanity check, type-specific, for known capabilities */
512 switch (caphdr.code)
513 {
514 case CAPABILITY_CODE_MP:
515 case CAPABILITY_CODE_REFRESH:
516 case CAPABILITY_CODE_REFRESH_OLD:
517 case CAPABILITY_CODE_ORF:
518 case CAPABILITY_CODE_ORF_OLD:
519 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000520 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000521 case CAPABILITY_CODE_DYNAMIC:
522 /* Check length. */
523 if (caphdr.length < cap_minsizes[caphdr.code])
524 {
525 zlog_info ("%s %s Capability length error: got %u,"
526 " expected at least %u",
527 peer->host,
528 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700529 caphdr.length,
530 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma68ec4242015-11-25 17:14:34 +0000531 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
532 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma6d582722007-08-06 15:21:45 +0000533 return -1;
534 }
Paul Jakma4078f2e2015-11-25 17:14:35 +0000535 if (caphdr.length
536 && caphdr.length % cap_modsizes[caphdr.code] != 0)
537 {
538 zlog_info ("%s %s Capability length error: got %u,"
539 " expected a multiple of %u",
540 peer->host,
541 LOOKUP (capcode_str, caphdr.code),
542 caphdr.length,
543 (unsigned) cap_modsizes[caphdr.code]);
544 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
545 BGP_NOTIFY_OPEN_UNSPECIFIC);
546 return -1;
547 }
Paul Jakma6d582722007-08-06 15:21:45 +0000548 /* we deliberately ignore unknown codes, see below */
549 default:
550 break;
551 }
552
553 switch (caphdr.code)
554 {
555 case CAPABILITY_CODE_MP:
556 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800557 *mp_capability = 1;
558
Paul Jakma6d582722007-08-06 15:21:45 +0000559 /* Ignore capability when override-capability is set. */
560 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
561 {
562 /* Set negotiated value. */
563 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000564
Paul Jakma6d582722007-08-06 15:21:45 +0000565 /* Unsupported Capability. */
566 if (ret < 0)
567 {
568 /* Store return data. */
569 memcpy (*error, sp, caphdr.length + 2);
570 *error += caphdr.length + 2;
571 }
572 }
573 }
574 break;
575 case CAPABILITY_CODE_REFRESH:
576 case CAPABILITY_CODE_REFRESH_OLD:
577 {
578 /* BGP refresh capability */
579 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
580 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
581 else
582 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
583 }
584 break;
585 case CAPABILITY_CODE_ORF:
586 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400587 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000588 return -1;
589 break;
590 case CAPABILITY_CODE_RESTART:
591 if (bgp_capability_restart (peer, &caphdr))
592 return -1;
593 break;
594 case CAPABILITY_CODE_DYNAMIC:
595 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
596 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000597 case CAPABILITY_CODE_AS4:
598 /* Already handled as a special-case parsing of the capabilities
599 * at the beginning of OPEN processing. So we care not a jot
600 * for the value really, only error case.
601 */
602 if (!bgp_capability_as4 (peer, &caphdr))
603 return -1;
604 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000605 default:
606 if (caphdr.code > 128)
607 {
608 /* We don't send Notification for unknown vendor specific
609 capabilities. It seems reasonable for now... */
610 zlog_warn ("%s Vendor specific capability %d",
611 peer->host, caphdr.code);
612 }
613 else
614 {
615 zlog_warn ("%s unrecognized capability code: %d - ignored",
616 peer->host, caphdr.code);
617 memcpy (*error, sp, caphdr.length + 2);
618 *error += caphdr.length + 2;
619 }
620 }
621 if (stream_get_getp(s) != (start + caphdr.length))
622 {
623 if (stream_get_getp(s) > (start + caphdr.length))
624 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
625 peer->host, LOOKUP (capcode_str, caphdr.code),
626 caphdr.length);
627 stream_set_getp (s, start + caphdr.length);
628 }
paul718e3742002-12-13 20:15:29 +0000629 }
630 return 0;
631}
632
paul94f2b392005-06-28 12:44:16 +0000633static int
Paul Jakma6d582722007-08-06 15:21:45 +0000634bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000635{
636 bgp_notify_send (peer,
637 BGP_NOTIFY_OPEN_ERR,
638 BGP_NOTIFY_OPEN_AUTH_FAILURE);
639 return -1;
640}
641
paul94f2b392005-06-28 12:44:16 +0000642static int
paul718e3742002-12-13 20:15:29 +0000643strict_capability_same (struct peer *peer)
644{
645 int i, j;
646
647 for (i = AFI_IP; i < AFI_MAX; i++)
648 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
649 if (peer->afc[i][j] != peer->afc_nego[i][j])
650 return 0;
651 return 1;
652}
653
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000654/* peek into option, stores ASN to *as4 if the AS4 capability was found.
655 * Returns 0 if no as4 found, as4cap value otherwise.
656 */
657as_t
658peek_for_as4_capability (struct peer *peer, u_char length)
659{
660 struct stream *s = BGP_INPUT (peer);
661 size_t orig_getp = stream_get_getp (s);
662 size_t end = orig_getp + length;
663 as_t as4 = 0;
664
665 /* The full capability parser will better flag the error.. */
666 if (STREAM_READABLE(s) < length)
667 return 0;
668
669 if (BGP_DEBUG (as4, AS4))
670 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
671 " peeking for as4",
672 peer->host, length);
673 /* the error cases we DONT handle, we ONLY try to read as4 out of
674 * correctly formatted options.
675 */
676 while (stream_get_getp(s) < end)
677 {
678 u_char opt_type;
679 u_char opt_length;
680
681 /* Check the length. */
682 if (stream_get_getp (s) + 2 > end)
683 goto end;
684
685 /* Fetch option type and length. */
686 opt_type = stream_getc (s);
687 opt_length = stream_getc (s);
688
689 /* Option length check. */
690 if (stream_get_getp (s) + opt_length > end)
691 goto end;
692
693 if (opt_type == BGP_OPEN_OPT_CAP)
694 {
695 unsigned long capd_start = stream_get_getp (s);
696 unsigned long capd_end = capd_start + opt_length;
697
698 assert (capd_end <= end);
699
700 while (stream_get_getp (s) < capd_end)
701 {
702 struct capability_header hdr;
703
704 if (stream_get_getp (s) + 2 > capd_end)
705 goto end;
706
707 hdr.code = stream_getc (s);
708 hdr.length = stream_getc (s);
709
710 if ((stream_get_getp(s) + hdr.length) > capd_end)
711 goto end;
712
713 if (hdr.code == CAPABILITY_CODE_AS4)
714 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000715 if (BGP_DEBUG (as4, AS4))
716 zlog_info ("[AS4] found AS4 capability, about to parse");
717 as4 = bgp_capability_as4 (peer, &hdr);
718
719 goto end;
720 }
721 stream_forward_getp (s, hdr.length);
722 }
723 }
724 }
725
726end:
727 stream_set_getp (s, orig_getp);
728 return as4;
729}
730
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800731/**
732 * Parse open option.
733 *
734 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
735 */
paul718e3742002-12-13 20:15:29 +0000736int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800737bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000738{
739 int ret;
paul718e3742002-12-13 20:15:29 +0000740 u_char *error;
741 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000742 struct stream *s = BGP_INPUT(peer);
743 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000744
745 ret = 0;
paul718e3742002-12-13 20:15:29 +0000746 error = error_data;
747
748 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000749 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000750 peer->host, length);
751
Paul Jakma6d582722007-08-06 15:21:45 +0000752 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000753 {
Paul Jakma6d582722007-08-06 15:21:45 +0000754 u_char opt_type;
755 u_char opt_length;
756
757 /* Must have at least an OPEN option header */
758 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000759 {
760 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000761 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
762 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000763 return -1;
764 }
765
766 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000767 opt_type = stream_getc (s);
768 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000769
770 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000771 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000772 {
773 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000774 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
775 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000776 return -1;
777 }
778
779 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000780 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000781 peer->host, opt_type,
782 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
783 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
784 opt_length);
785
786 switch (opt_type)
787 {
788 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000789 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000790 break;
791 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800792 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000793 break;
794 default:
795 bgp_notify_send (peer,
796 BGP_NOTIFY_OPEN_ERR,
797 BGP_NOTIFY_OPEN_UNSUP_PARAM);
798 ret = -1;
799 break;
800 }
801
802 /* Parse error. To accumulate all unsupported capability codes,
803 bgp_capability_parse does not return -1 when encounter
804 unsupported capability code. To detect that, please check
805 error and erro_data pointer, like below. */
806 if (ret < 0)
807 return -1;
paul718e3742002-12-13 20:15:29 +0000808 }
809
810 /* All OPEN option is parsed. Check capability when strict compare
811 flag is enabled.*/
812 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
813 {
814 /* If Unsupported Capability exists. */
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 return -1;
822 }
823
824 /* Check local capability does not negotiated with remote
825 peer. */
826 if (! strict_capability_same (peer))
827 {
828 bgp_notify_send (peer,
829 BGP_NOTIFY_OPEN_ERR,
830 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
831 return -1;
832 }
833 }
834
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800835 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000836 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800837 if (*mp_capability &&
838 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000839 {
840 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
841 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
842 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
843 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
844 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
845 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800846 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
847 "overlap with received MP capabilities",
848 peer->host);
paul718e3742002-12-13 20:15:29 +0000849
850 if (error != error_data)
851
852 bgp_notify_send_with_data (peer,
853 BGP_NOTIFY_OPEN_ERR,
854 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
855 error_data, error - error_data);
856 else
857 bgp_notify_send (peer,
858 BGP_NOTIFY_OPEN_ERR,
859 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
860 return -1;
861 }
862 }
863 return 0;
864}
865
paul94f2b392005-06-28 12:44:16 +0000866static void
paul718e3742002-12-13 20:15:29 +0000867bgp_open_capability_orf (struct stream *s, struct peer *peer,
868 afi_t afi, safi_t safi, u_char code)
869{
870 u_char cap_len;
871 u_char orf_len;
872 unsigned long capp;
873 unsigned long orfp;
874 unsigned long numberp;
875 int number_of_orfs = 0;
876
877 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400878 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000879
880 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000881 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000882 stream_putc (s, 0); /* Capability Length */
883 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000884 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000885 stream_putc (s, 0); /* ORF Length */
886 stream_putw (s, afi);
887 stream_putc (s, 0);
888 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000889 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000890 stream_putc (s, 0); /* Number of ORFs */
891
892 /* Address Prefix ORF */
893 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
894 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
895 {
896 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
897 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
898
899 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
900 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
901 {
902 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
903 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
904 stream_putc (s, ORF_MODE_BOTH);
905 }
906 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
907 {
908 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
909 stream_putc (s, ORF_MODE_SEND);
910 }
911 else
912 {
913 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
914 stream_putc (s, ORF_MODE_RECEIVE);
915 }
916 number_of_orfs++;
917 }
918
919 /* Total Number of ORFs. */
920 stream_putc_at (s, numberp, number_of_orfs);
921
922 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000923 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000924 stream_putc_at (s, orfp, orf_len);
925
926 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000927 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000928 stream_putc_at (s, capp, cap_len);
929}
930
931/* Fill in capability open option to the packet. */
932void
933bgp_open_capability (struct stream *s, struct peer *peer)
934{
935 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700936 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000937 afi_t afi;
938 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000939 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700940 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000941
942 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000943 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000944
945 /* Opt Parm Len. */
946 stream_putc (s, 0);
947
948 /* Do not send capability. */
949 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
950 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
951 return;
952
paul718e3742002-12-13 20:15:29 +0000953 /* IPv4 unicast. */
954 if (peer->afc[AFI_IP][SAFI_UNICAST])
955 {
956 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
957 stream_putc (s, BGP_OPEN_OPT_CAP);
958 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
959 stream_putc (s, CAPABILITY_CODE_MP);
960 stream_putc (s, CAPABILITY_CODE_MP_LEN);
961 stream_putw (s, AFI_IP);
962 stream_putc (s, 0);
963 stream_putc (s, SAFI_UNICAST);
964 }
965 /* IPv4 multicast. */
966 if (peer->afc[AFI_IP][SAFI_MULTICAST])
967 {
968 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
969 stream_putc (s, BGP_OPEN_OPT_CAP);
970 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
971 stream_putc (s, CAPABILITY_CODE_MP);
972 stream_putc (s, CAPABILITY_CODE_MP_LEN);
973 stream_putw (s, AFI_IP);
974 stream_putc (s, 0);
975 stream_putc (s, SAFI_MULTICAST);
976 }
977 /* IPv4 VPN */
978 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
979 {
980 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
981 stream_putc (s, BGP_OPEN_OPT_CAP);
982 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
983 stream_putc (s, CAPABILITY_CODE_MP);
984 stream_putc (s, CAPABILITY_CODE_MP_LEN);
985 stream_putw (s, AFI_IP);
986 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400987 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000988 }
989#ifdef HAVE_IPV6
990 /* IPv6 unicast. */
991 if (peer->afc[AFI_IP6][SAFI_UNICAST])
992 {
993 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
994 stream_putc (s, BGP_OPEN_OPT_CAP);
995 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
996 stream_putc (s, CAPABILITY_CODE_MP);
997 stream_putc (s, CAPABILITY_CODE_MP_LEN);
998 stream_putw (s, AFI_IP6);
999 stream_putc (s, 0);
1000 stream_putc (s, SAFI_UNICAST);
1001 }
1002 /* IPv6 multicast. */
1003 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1004 {
1005 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
1006 stream_putc (s, BGP_OPEN_OPT_CAP);
1007 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1008 stream_putc (s, CAPABILITY_CODE_MP);
1009 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1010 stream_putw (s, AFI_IP6);
1011 stream_putc (s, 0);
1012 stream_putc (s, SAFI_MULTICAST);
1013 }
1014#endif /* HAVE_IPV6 */
1015
1016 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001017 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1018 stream_putc (s, BGP_OPEN_OPT_CAP);
1019 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1020 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1021 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1022 stream_putc (s, BGP_OPEN_OPT_CAP);
1023 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1024 stream_putc (s, CAPABILITY_CODE_REFRESH);
1025 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001026
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001027 /* AS4 */
1028 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1029 stream_putc (s, BGP_OPEN_OPT_CAP);
1030 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1031 stream_putc (s, CAPABILITY_CODE_AS4);
1032 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1033 if ( peer->change_local_as )
1034 local_as = peer->change_local_as;
1035 else
1036 local_as = peer->local_as;
1037 stream_putl (s, local_as );
1038
paul718e3742002-12-13 20:15:29 +00001039 /* ORF capability. */
1040 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1041 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1042 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1043 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1044 {
1045 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1046 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1047 }
1048
1049 /* Dynamic capability. */
1050 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1051 {
1052 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1053 stream_putc (s, BGP_OPEN_OPT_CAP);
1054 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1055 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1056 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1057 }
1058
Vipin Kumardd49eb12014-09-30 14:36:38 -07001059 /* Sending base graceful-restart capability irrespective of the config */
1060 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1061 stream_putc (s, BGP_OPEN_OPT_CAP);
1062 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1063 stream_putc (s, 0); /* Capability Length */
1064 stream_putc (s, CAPABILITY_CODE_RESTART);
1065 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1066 stream_putc (s, 0);
1067 restart_time = peer->bgp->restart_time;
1068 if (peer->bgp->t_startup)
1069 {
1070 SET_FLAG (restart_time, RESTART_R_BIT);
1071 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1072 }
1073 stream_putw (s, restart_time);
1074
1075 /* Send address-family specific graceful-restart capability only when GR config
1076 is present */
hasso538621f2004-05-21 09:31:30 +00001077 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1078 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001079 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1080 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1081 if (peer->afc[afi][safi])
1082 {
1083 stream_putw (s, afi);
1084 stream_putc (s, safi);
1085 stream_putc (s, 0); //Forwarding is not retained as of now.
1086 }
1087 }
1088
1089 /* Total Graceful restart capability Len. */
1090 len = stream_get_endp (s) - rcapp - 1;
1091 stream_putc_at (s, rcapp, len);
1092
1093 /* Total Capability Len. */
1094 len = stream_get_endp (s) - capp - 1;
1095 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001096
paul718e3742002-12-13 20:15:29 +00001097 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001098 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001099 stream_putc_at (s, cp, len);
1100}