blob: 7a5f5ce0caaa70b495dbdb584ffb8cae0d349da1 [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"
Donald Sharp04907292016-01-07 10:03:01 -050030#include "filter.h"
paul718e3742002-12-13 20:15:29 +000031
32#include "bgpd/bgpd.h"
33#include "bgpd/bgp_attr.h"
34#include "bgpd/bgp_debug.h"
35#include "bgpd/bgp_fsm.h"
36#include "bgpd/bgp_packet.h"
37#include "bgpd/bgp_open.h"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000038#include "bgpd/bgp_aspath.h"
hasso538621f2004-05-21 09:31:30 +000039#include "bgpd/bgp_vty.h"
40
paul718e3742002-12-13 20:15:29 +000041/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
42 negotiate remote peer supports extentions or not. But if
43 remote-peer doesn't supports negotiation process itself. We would
44 like to do manual configuration.
45
46 So there is many configurable point. First of all we want set each
47 peer whether we send capability negotiation to the peer or not.
48 Next, if we send capability to the peer we want to set my capabilty
49 inforation at each peer. */
50
51void
52bgp_capability_vty_out (struct vty *vty, struct peer *peer)
53{
paul5228ad22004-06-04 17:58:18 +000054 char *pnt;
55 char *end;
Paul Jakma6d582722007-08-06 15:21:45 +000056 struct capability_mp_data mpc;
57 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +000058
59 pnt = peer->notify.data;
60 end = pnt + peer->notify.length;
Paul Jakma6d582722007-08-06 15:21:45 +000061
paul718e3742002-12-13 20:15:29 +000062 while (pnt < end)
63 {
Paul Jakma6d582722007-08-06 15:21:45 +000064 if (pnt + sizeof (struct capability_mp_data) + 2 > end)
paul718e3742002-12-13 20:15:29 +000065 return;
Paul Jakma6d582722007-08-06 15:21:45 +000066
67 hdr = (struct capability_header *)pnt;
68 if (pnt + hdr->length + 2 > end)
paul718e3742002-12-13 20:15:29 +000069 return;
70
Paul Jakma6d582722007-08-06 15:21:45 +000071 memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
72
73 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +000074 {
75 vty_out (vty, " Capability error for: Multi protocol ");
76
Paul Jakma6d582722007-08-06 15:21:45 +000077 switch (ntohs (mpc.afi))
paul718e3742002-12-13 20:15:29 +000078 {
79 case AFI_IP:
80 vty_out (vty, "AFI IPv4, ");
81 break;
82 case AFI_IP6:
83 vty_out (vty, "AFI IPv6, ");
84 break;
85 default:
Paul Jakma6d582722007-08-06 15:21:45 +000086 vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
paul718e3742002-12-13 20:15:29 +000087 break;
88 }
Paul Jakma6d582722007-08-06 15:21:45 +000089 switch (mpc.safi)
paul718e3742002-12-13 20:15:29 +000090 {
91 case SAFI_UNICAST:
92 vty_out (vty, "SAFI Unicast");
93 break;
94 case SAFI_MULTICAST:
95 vty_out (vty, "SAFI Multicast");
96 break;
Denis Ovsienko42e6d742011-07-14 12:36:19 +040097 case SAFI_MPLS_LABELED_VPN:
98 vty_out (vty, "SAFI MPLS-labeled VPN");
paul718e3742002-12-13 20:15:29 +000099 break;
100 default:
Paul Jakma6d582722007-08-06 15:21:45 +0000101 vty_out (vty, "SAFI Unknown %d ", mpc.safi);
paul718e3742002-12-13 20:15:29 +0000102 break;
103 }
104 vty_out (vty, "%s", VTY_NEWLINE);
105 }
Paul Jakma6d582722007-08-06 15:21:45 +0000106 else if (hdr->code >= 128)
paul718e3742002-12-13 20:15:29 +0000107 vty_out (vty, " Capability error: vendor specific capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000108 hdr->code);
paul718e3742002-12-13 20:15:29 +0000109 else
110 vty_out (vty, " Capability error: unknown capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000111 hdr->code);
paul718e3742002-12-13 20:15:29 +0000112
Paul Jakma6d582722007-08-06 15:21:45 +0000113 pnt += hdr->length + 2;
paul718e3742002-12-13 20:15:29 +0000114 }
115}
116
Paul Jakma6d582722007-08-06 15:21:45 +0000117static void
118bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
119{
120 mpc->afi = stream_getw (s);
121 mpc->reserved = stream_getc (s);
122 mpc->safi = stream_getc (s);
123}
124
125int
126bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
127{
Paul Jakma6d582722007-08-06 15:21:45 +0000128 switch (afi)
129 {
Donald Sharpf3cfc462016-01-07 09:33:28 -0500130 case AFI_IP:
131 case AFI_IP6:
132 switch (*safi)
133 {
134 /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
135 case SAFI_MPLS_LABELED_VPN:
136 *safi = SAFI_MPLS_VPN;
137 case SAFI_UNICAST:
138 case SAFI_MULTICAST:
139 case SAFI_MPLS_VPN:
140 return 1;
141 }
142 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000143 }
Donald Sharpf3cfc462016-01-07 09:33:28 -0500144
Paul Jakma6d582722007-08-06 15:21:45 +0000145 zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
Donald Sharpf3cfc462016-01-07 09:33:28 -0500146
Paul Jakma6d582722007-08-06 15:21:45 +0000147 return 0;
148}
149
paul718e3742002-12-13 20:15:29 +0000150/* Set negotiated capability value. */
paul94f2b392005-06-28 12:44:16 +0000151static int
Paul Jakma6d582722007-08-06 15:21:45 +0000152bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
paul718e3742002-12-13 20:15:29 +0000153{
Paul Jakma6d582722007-08-06 15:21:45 +0000154 struct capability_mp_data mpc;
155 struct stream *s = BGP_INPUT (peer);
156
157 bgp_capability_mp_data (s, &mpc);
158
159 if (BGP_DEBUG (normal, NORMAL))
160 zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
161 peer->host, mpc.afi, mpc.safi);
162
163 if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
164 return -1;
165
166 /* Now safi remapped, and afi/safi are valid array indices */
167 peer->afc_recv[mpc.afi][mpc.safi] = 1;
168
169 if (peer->afc[mpc.afi][mpc.safi])
Paul Jakmae08286b2007-09-18 12:11:26 +0000170 peer->afc_nego[mpc.afi][mpc.safi] = 1;
Paul Jakma6d582722007-08-06 15:21:45 +0000171 else
172 return -1;
paul718e3742002-12-13 20:15:29 +0000173
174 return 0;
175}
176
paul94f2b392005-06-28 12:44:16 +0000177static void
paul718e3742002-12-13 20:15:29 +0000178bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
179 u_char type, u_char mode)
180{
181 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000182 zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
paul718e3742002-12-13 20:15:29 +0000183 peer->host, afi, safi, type, mode);
184}
185
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700186static const struct message orf_type_str[] =
paul718e3742002-12-13 20:15:29 +0000187{
Paul Jakma6d582722007-08-06 15:21:45 +0000188 { ORF_TYPE_PREFIX, "Prefixlist" },
189 { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
190};
Balaji.G837d16c2012-09-26 14:09:10 +0530191static const int orf_type_str_max = array_size(orf_type_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000192
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700193static const struct message orf_mode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000194{
195 { ORF_MODE_RECEIVE, "Receive" },
196 { ORF_MODE_SEND, "Send" },
197 { ORF_MODE_BOTH, "Both" },
198};
Balaji.G837d16c2012-09-26 14:09:10 +0530199static const int orf_mode_str_max = array_size(orf_mode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000200
201static int
202bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
203{
204 struct stream *s = BGP_INPUT (peer);
205 struct capability_orf_entry entry;
206 afi_t afi;
207 safi_t safi;
paul718e3742002-12-13 20:15:29 +0000208 u_char type;
209 u_char mode;
210 u_int16_t sm_cap = 0; /* capability send-mode receive */
211 u_int16_t rm_cap = 0; /* capability receive-mode receive */
212 int i;
213
Paul Jakma6d582722007-08-06 15:21:45 +0000214 /* ORF Entry header */
215 bgp_capability_mp_data (s, &entry.mpc);
216 entry.num = stream_getc (s);
217 afi = entry.mpc.afi;
218 safi = entry.mpc.safi;
219
paul718e3742002-12-13 20:15:29 +0000220 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma6d582722007-08-06 15:21:45 +0000221 zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
222 peer->host, entry.mpc.afi, entry.mpc.safi);
paul718e3742002-12-13 20:15:29 +0000223
224 /* Check AFI and SAFI. */
Paul Jakma6d582722007-08-06 15:21:45 +0000225 if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
paul718e3742002-12-13 20:15:29 +0000226 {
Paul Jakma6d582722007-08-06 15:21:45 +0000227 zlog_info ("%s Addr-family %d/%d not supported."
228 " Ignoring the ORF capability",
229 peer->host, entry.mpc.afi, entry.mpc.safi);
230 return 0;
231 }
232
233 /* validate number field */
Donald Sharpf3cfc462016-01-07 09:33:28 -0500234 if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length)
Paul Jakma6d582722007-08-06 15:21:45 +0000235 {
236 zlog_info ("%s ORF Capability entry length error,"
237 " Cap length %u, num %u",
238 peer->host, hdr->length, entry.num);
Paul Jakma68ec4242015-11-25 17:14:34 +0000239 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000240 return -1;
241 }
242
Paul Jakma6d582722007-08-06 15:21:45 +0000243 for (i = 0 ; i < entry.num ; i++)
paul718e3742002-12-13 20:15:29 +0000244 {
Paul Jakma6d582722007-08-06 15:21:45 +0000245 type = stream_getc(s);
246 mode = stream_getc(s);
247
paul718e3742002-12-13 20:15:29 +0000248 /* ORF Mode error check */
Paul Jakma6d582722007-08-06 15:21:45 +0000249 switch (mode)
250 {
251 case ORF_MODE_BOTH:
252 case ORF_MODE_SEND:
253 case ORF_MODE_RECEIVE:
254 break;
255 default:
256 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
257 continue;
paul718e3742002-12-13 20:15:29 +0000258 }
Paul Jakma6d582722007-08-06 15:21:45 +0000259 /* ORF Type and afi/safi error checks */
260 /* capcode versus type */
261 switch (hdr->code)
262 {
263 case CAPABILITY_CODE_ORF:
264 switch (type)
265 {
266 case ORF_TYPE_PREFIX:
267 break;
268 default:
269 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
270 continue;
271 }
272 break;
273 case CAPABILITY_CODE_ORF_OLD:
274 switch (type)
275 {
276 case ORF_TYPE_PREFIX_OLD:
277 break;
278 default:
279 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
280 continue;
281 }
282 break;
283 default:
284 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
285 continue;
286 }
287
288 /* AFI vs SAFI */
289 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
290 || (afi == AFI_IP && safi == SAFI_MULTICAST)
291 || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
292 {
293 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
294 continue;
295 }
296
297 if (BGP_DEBUG (normal, NORMAL))
298 zlog_debug ("%s OPEN has %s ORF capability"
299 " as %s for afi/safi: %d/%d",
300 peer->host, LOOKUP (orf_type_str, type),
301 LOOKUP (orf_mode_str, mode),
302 entry.mpc.afi, safi);
paul718e3742002-12-13 20:15:29 +0000303
Paul Jakma6d582722007-08-06 15:21:45 +0000304 if (hdr->code == CAPABILITY_CODE_ORF)
paul718e3742002-12-13 20:15:29 +0000305 {
Paul Jakma6d582722007-08-06 15:21:45 +0000306 sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
307 rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
paul718e3742002-12-13 20:15:29 +0000308 }
Paul Jakma6d582722007-08-06 15:21:45 +0000309 else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
paul718e3742002-12-13 20:15:29 +0000310 {
Paul Jakma6d582722007-08-06 15:21:45 +0000311 sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
312 rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
paul718e3742002-12-13 20:15:29 +0000313 }
314 else
315 {
316 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
317 continue;
318 }
319
320 switch (mode)
321 {
322 case ORF_MODE_BOTH:
323 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
324 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
325 break;
326 case ORF_MODE_SEND:
327 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
328 break;
329 case ORF_MODE_RECEIVE:
330 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
331 break;
332 }
333 }
334 return 0;
335}
336
paul94f2b392005-06-28 12:44:16 +0000337static int
Paul Jakma6d582722007-08-06 15:21:45 +0000338bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
339{
340 struct stream *s = BGP_INPUT (peer);
341 u_int16_t restart_flag_time;
Paul Jakma6d582722007-08-06 15:21:45 +0000342 size_t end = stream_get_getp (s) + caphdr->length;
343
344 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
345 restart_flag_time = stream_getw(s);
346 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
Paul Jakmaec98d902014-10-14 11:14:06 +0100347 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
348
Paul Jakma6d582722007-08-06 15:21:45 +0000349 UNSET_FLAG (restart_flag_time, 0xF000);
350 peer->v_gr_restart = restart_flag_time;
351
352 if (BGP_DEBUG (normal, NORMAL))
353 {
354 zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
355 zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
Paul Jakmaec98d902014-10-14 11:14:06 +0100356 peer->host,
357 CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " "
358 : " not ",
Paul Jakma6d582722007-08-06 15:21:45 +0000359 peer->v_gr_restart);
360 }
361
Peter Pentchev21cc7692011-09-12 16:30:31 +0400362 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000363 {
364 afi_t afi = stream_getw (s);
365 safi_t safi = stream_getc (s);
366 u_char flag = stream_getc (s);
367
368 if (!bgp_afi_safi_valid_indices (afi, &safi))
369 {
370 if (BGP_DEBUG (normal, NORMAL))
371 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
372 " Ignore the Graceful Restart capability",
373 peer->host, afi, safi);
374 }
375 else if (!peer->afc[afi][safi])
376 {
377 if (BGP_DEBUG (normal, NORMAL))
378 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
379 " Ignore the Graceful Restart capability",
380 peer->host, afi, safi);
381 }
382 else
383 {
384 if (BGP_DEBUG (normal, NORMAL))
385 zlog_debug ("%s Address family %s is%spreserved", peer->host,
386 afi_safi_print (afi, safi),
387 CHECK_FLAG (peer->af_cap[afi][safi],
388 PEER_CAP_RESTART_AF_PRESERVE_RCV)
389 ? " " : " not ");
390
391 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
392 if (CHECK_FLAG (flag, RESTART_F_BIT))
393 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
394
395 }
396 }
397 return 0;
398}
399
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000400static as_t
401bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
402{
Paul Jakma58617392012-01-09 20:59:26 +0000403 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
404
405 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
406 {
407 zlog_err ("%s AS4 capability has incorrect data length %d",
408 peer->host, hdr->length);
409 return 0;
410 }
411
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000412 as_t as4 = stream_getl (BGP_INPUT(peer));
413
414 if (BGP_DEBUG (as4, AS4))
415 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
416 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000417 return as4;
418}
419
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700420static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000421{
Paul Jakma6d582722007-08-06 15:21:45 +0000422 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
423 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
424 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
425 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
426 { CAPABILITY_CODE_AS4, "4-octet AS number" },
427 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
428 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
429 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
430};
Balaji.G837d16c2012-09-26 14:09:10 +0530431static const int capcode_str_max = array_size(capcode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000432
433/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700434static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000435{
Donald Sharpf3cfc462016-01-07 09:33:28 -0500436 [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000437 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500438 [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
Lou Berger7748fdc2016-02-10 14:24:00 +0000439 [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000440 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
441 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
442 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500443 [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000444};
445
Paul Jakma4078f2e2015-11-25 17:14:35 +0000446/* value the capability must be a multiple of.
447 * 0-data capabilities won't be checked against this.
448 * Other capabilities whose data doesn't fall on convenient boundaries for this
449 * table should be set to 1.
450 */
451static const size_t cap_modsizes[] =
452{
453 [CAPABILITY_CODE_MP] = 4,
454 [CAPABILITY_CODE_REFRESH] = 1,
455 [CAPABILITY_CODE_ORF] = 1,
456 [CAPABILITY_CODE_RESTART] = 1,
457 [CAPABILITY_CODE_AS4] = 4,
458 [CAPABILITY_CODE_DYNAMIC] = 1,
459 [CAPABILITY_CODE_REFRESH_OLD] = 1,
460 [CAPABILITY_CODE_ORF_OLD] = 1,
461};
462
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800463/**
464 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000465 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800466 *
467 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
468 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000469 */
470static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800471bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
472 u_char **error)
paul718e3742002-12-13 20:15:29 +0000473{
474 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000475 struct stream *s = BGP_INPUT (peer);
476 size_t end = stream_get_getp (s) + length;
477
478 assert (STREAM_READABLE (s) >= length);
479
480 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000481 {
Paul Jakma6d582722007-08-06 15:21:45 +0000482 size_t start;
483 u_char *sp = stream_pnt (s);
484 struct capability_header caphdr;
485
paul718e3742002-12-13 20:15:29 +0000486 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000487 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000488 {
Paul Jakma6d582722007-08-06 15:21:45 +0000489 zlog_info ("%s Capability length error (< header)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000490 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000491 return -1;
492 }
Paul Jakma6d582722007-08-06 15:21:45 +0000493
494 caphdr.code = stream_getc (s);
495 caphdr.length = stream_getc (s);
496 start = stream_get_getp (s);
497
498 /* Capability length check sanity check. */
499 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000500 {
Paul Jakma6d582722007-08-06 15:21:45 +0000501 zlog_info ("%s Capability length error (< length)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000502 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000503 return -1;
504 }
Paul Jakma6d582722007-08-06 15:21:45 +0000505
506 if (BGP_DEBUG (normal, NORMAL))
507 zlog_debug ("%s OPEN has %s capability (%u), length %u",
508 peer->host,
509 LOOKUP (capcode_str, caphdr.code),
510 caphdr.code, caphdr.length);
511
512 /* Length sanity check, type-specific, for known capabilities */
513 switch (caphdr.code)
514 {
515 case CAPABILITY_CODE_MP:
516 case CAPABILITY_CODE_REFRESH:
517 case CAPABILITY_CODE_REFRESH_OLD:
518 case CAPABILITY_CODE_ORF:
519 case CAPABILITY_CODE_ORF_OLD:
520 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000521 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000522 case CAPABILITY_CODE_DYNAMIC:
523 /* Check length. */
524 if (caphdr.length < cap_minsizes[caphdr.code])
525 {
526 zlog_info ("%s %s Capability length error: got %u,"
527 " expected at least %u",
528 peer->host,
529 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700530 caphdr.length,
531 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma68ec4242015-11-25 17:14:34 +0000532 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
533 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma6d582722007-08-06 15:21:45 +0000534 return -1;
535 }
Paul Jakma4078f2e2015-11-25 17:14:35 +0000536 if (caphdr.length
537 && caphdr.length % cap_modsizes[caphdr.code] != 0)
538 {
539 zlog_info ("%s %s Capability length error: got %u,"
540 " expected a multiple of %u",
541 peer->host,
542 LOOKUP (capcode_str, caphdr.code),
543 caphdr.length,
544 (unsigned) cap_modsizes[caphdr.code]);
545 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
546 BGP_NOTIFY_OPEN_UNSPECIFIC);
547 return -1;
548 }
Paul Jakma6d582722007-08-06 15:21:45 +0000549 /* we deliberately ignore unknown codes, see below */
550 default:
551 break;
552 }
553
554 switch (caphdr.code)
555 {
556 case CAPABILITY_CODE_MP:
557 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800558 *mp_capability = 1;
559
Paul Jakma6d582722007-08-06 15:21:45 +0000560 /* Ignore capability when override-capability is set. */
561 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
562 {
563 /* Set negotiated value. */
564 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000565
Paul Jakma6d582722007-08-06 15:21:45 +0000566 /* Unsupported Capability. */
567 if (ret < 0)
568 {
569 /* Store return data. */
570 memcpy (*error, sp, caphdr.length + 2);
571 *error += caphdr.length + 2;
572 }
573 }
574 }
575 break;
576 case CAPABILITY_CODE_REFRESH:
577 case CAPABILITY_CODE_REFRESH_OLD:
578 {
579 /* BGP refresh capability */
580 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
581 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
582 else
583 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
584 }
585 break;
586 case CAPABILITY_CODE_ORF:
587 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400588 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000589 return -1;
590 break;
591 case CAPABILITY_CODE_RESTART:
592 if (bgp_capability_restart (peer, &caphdr))
593 return -1;
594 break;
595 case CAPABILITY_CODE_DYNAMIC:
596 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
597 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000598 case CAPABILITY_CODE_AS4:
599 /* Already handled as a special-case parsing of the capabilities
600 * at the beginning of OPEN processing. So we care not a jot
601 * for the value really, only error case.
602 */
603 if (!bgp_capability_as4 (peer, &caphdr))
604 return -1;
605 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000606 default:
607 if (caphdr.code > 128)
608 {
609 /* We don't send Notification for unknown vendor specific
610 capabilities. It seems reasonable for now... */
611 zlog_warn ("%s Vendor specific capability %d",
612 peer->host, caphdr.code);
613 }
614 else
615 {
616 zlog_warn ("%s unrecognized capability code: %d - ignored",
617 peer->host, caphdr.code);
618 memcpy (*error, sp, caphdr.length + 2);
619 *error += caphdr.length + 2;
620 }
621 }
622 if (stream_get_getp(s) != (start + caphdr.length))
623 {
624 if (stream_get_getp(s) > (start + caphdr.length))
625 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
626 peer->host, LOOKUP (capcode_str, caphdr.code),
627 caphdr.length);
628 stream_set_getp (s, start + caphdr.length);
629 }
paul718e3742002-12-13 20:15:29 +0000630 }
631 return 0;
632}
633
paul94f2b392005-06-28 12:44:16 +0000634static int
Paul Jakma6d582722007-08-06 15:21:45 +0000635bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000636{
637 bgp_notify_send (peer,
638 BGP_NOTIFY_OPEN_ERR,
639 BGP_NOTIFY_OPEN_AUTH_FAILURE);
640 return -1;
641}
642
paul94f2b392005-06-28 12:44:16 +0000643static int
paul718e3742002-12-13 20:15:29 +0000644strict_capability_same (struct peer *peer)
645{
646 int i, j;
647
648 for (i = AFI_IP; i < AFI_MAX; i++)
649 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
650 if (peer->afc[i][j] != peer->afc_nego[i][j])
651 return 0;
652 return 1;
653}
654
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000655/* peek into option, stores ASN to *as4 if the AS4 capability was found.
656 * Returns 0 if no as4 found, as4cap value otherwise.
657 */
658as_t
659peek_for_as4_capability (struct peer *peer, u_char length)
660{
661 struct stream *s = BGP_INPUT (peer);
662 size_t orig_getp = stream_get_getp (s);
663 size_t end = orig_getp + length;
664 as_t as4 = 0;
665
666 /* The full capability parser will better flag the error.. */
667 if (STREAM_READABLE(s) < length)
668 return 0;
669
670 if (BGP_DEBUG (as4, AS4))
671 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
672 " peeking for as4",
673 peer->host, length);
674 /* the error cases we DONT handle, we ONLY try to read as4 out of
675 * correctly formatted options.
676 */
677 while (stream_get_getp(s) < end)
678 {
679 u_char opt_type;
680 u_char opt_length;
681
682 /* Check the length. */
683 if (stream_get_getp (s) + 2 > end)
684 goto end;
685
686 /* Fetch option type and length. */
687 opt_type = stream_getc (s);
688 opt_length = stream_getc (s);
689
690 /* Option length check. */
691 if (stream_get_getp (s) + opt_length > end)
692 goto end;
693
694 if (opt_type == BGP_OPEN_OPT_CAP)
695 {
696 unsigned long capd_start = stream_get_getp (s);
697 unsigned long capd_end = capd_start + opt_length;
698
699 assert (capd_end <= end);
700
701 while (stream_get_getp (s) < capd_end)
702 {
703 struct capability_header hdr;
704
705 if (stream_get_getp (s) + 2 > capd_end)
706 goto end;
707
708 hdr.code = stream_getc (s);
709 hdr.length = stream_getc (s);
710
711 if ((stream_get_getp(s) + hdr.length) > capd_end)
712 goto end;
713
714 if (hdr.code == CAPABILITY_CODE_AS4)
715 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000716 if (BGP_DEBUG (as4, AS4))
717 zlog_info ("[AS4] found AS4 capability, about to parse");
718 as4 = bgp_capability_as4 (peer, &hdr);
719
720 goto end;
721 }
722 stream_forward_getp (s, hdr.length);
723 }
724 }
725 }
726
727end:
728 stream_set_getp (s, orig_getp);
729 return as4;
730}
731
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800732/**
733 * Parse open option.
734 *
735 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
736 */
paul718e3742002-12-13 20:15:29 +0000737int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800738bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000739{
740 int ret;
paul718e3742002-12-13 20:15:29 +0000741 u_char *error;
742 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000743 struct stream *s = BGP_INPUT(peer);
744 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000745
746 ret = 0;
paul718e3742002-12-13 20:15:29 +0000747 error = error_data;
748
749 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000750 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000751 peer->host, length);
752
Paul Jakma6d582722007-08-06 15:21:45 +0000753 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000754 {
Paul Jakma6d582722007-08-06 15:21:45 +0000755 u_char opt_type;
756 u_char opt_length;
757
758 /* Must have at least an OPEN option header */
759 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000760 {
761 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000762 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
763 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000764 return -1;
765 }
766
767 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000768 opt_type = stream_getc (s);
769 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000770
771 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000772 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000773 {
774 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000775 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
776 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000777 return -1;
778 }
779
780 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000781 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000782 peer->host, opt_type,
783 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
784 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
785 opt_length);
786
787 switch (opt_type)
788 {
789 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000790 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000791 break;
792 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800793 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000794 break;
795 default:
796 bgp_notify_send (peer,
797 BGP_NOTIFY_OPEN_ERR,
798 BGP_NOTIFY_OPEN_UNSUP_PARAM);
799 ret = -1;
800 break;
801 }
802
803 /* Parse error. To accumulate all unsupported capability codes,
804 bgp_capability_parse does not return -1 when encounter
805 unsupported capability code. To detect that, please check
806 error and erro_data pointer, like below. */
807 if (ret < 0)
808 return -1;
paul718e3742002-12-13 20:15:29 +0000809 }
810
811 /* All OPEN option is parsed. Check capability when strict compare
812 flag is enabled.*/
813 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
814 {
815 /* If Unsupported Capability exists. */
816 if (error != error_data)
817 {
818 bgp_notify_send_with_data (peer,
819 BGP_NOTIFY_OPEN_ERR,
820 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
821 error_data, error - error_data);
822 return -1;
823 }
824
825 /* Check local capability does not negotiated with remote
826 peer. */
827 if (! strict_capability_same (peer))
828 {
829 bgp_notify_send (peer,
830 BGP_NOTIFY_OPEN_ERR,
831 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
832 return -1;
833 }
834 }
835
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800836 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000837 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800838 if (*mp_capability &&
839 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000840 {
841 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
842 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
843 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
844 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
845 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
846 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800847 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
848 "overlap with received MP capabilities",
849 peer->host);
paul718e3742002-12-13 20:15:29 +0000850
851 if (error != error_data)
852
853 bgp_notify_send_with_data (peer,
854 BGP_NOTIFY_OPEN_ERR,
855 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
856 error_data, error - error_data);
857 else
858 bgp_notify_send (peer,
859 BGP_NOTIFY_OPEN_ERR,
860 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
861 return -1;
862 }
863 }
864 return 0;
865}
866
paul94f2b392005-06-28 12:44:16 +0000867static void
paul718e3742002-12-13 20:15:29 +0000868bgp_open_capability_orf (struct stream *s, struct peer *peer,
869 afi_t afi, safi_t safi, u_char code)
870{
871 u_char cap_len;
872 u_char orf_len;
873 unsigned long capp;
874 unsigned long orfp;
875 unsigned long numberp;
876 int number_of_orfs = 0;
877
878 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400879 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000880
881 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000882 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000883 stream_putc (s, 0); /* Capability Length */
884 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000885 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000886 stream_putc (s, 0); /* ORF Length */
887 stream_putw (s, afi);
888 stream_putc (s, 0);
889 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000890 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000891 stream_putc (s, 0); /* Number of ORFs */
892
893 /* Address Prefix ORF */
894 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
895 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
896 {
897 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
898 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
899
900 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
901 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
902 {
903 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
904 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
905 stream_putc (s, ORF_MODE_BOTH);
906 }
907 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
908 {
909 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
910 stream_putc (s, ORF_MODE_SEND);
911 }
912 else
913 {
914 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
915 stream_putc (s, ORF_MODE_RECEIVE);
916 }
917 number_of_orfs++;
918 }
919
920 /* Total Number of ORFs. */
921 stream_putc_at (s, numberp, number_of_orfs);
922
923 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000924 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000925 stream_putc_at (s, orfp, orf_len);
926
927 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000928 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000929 stream_putc_at (s, capp, cap_len);
930}
931
932/* Fill in capability open option to the packet. */
933void
934bgp_open_capability (struct stream *s, struct peer *peer)
935{
936 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700937 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000938 afi_t afi;
939 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000940 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700941 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000942
943 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000944 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000945
946 /* Opt Parm Len. */
947 stream_putc (s, 0);
948
949 /* Do not send capability. */
950 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
951 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
952 return;
953
paul718e3742002-12-13 20:15:29 +0000954 /* IPv4 unicast. */
955 if (peer->afc[AFI_IP][SAFI_UNICAST])
956 {
957 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
958 stream_putc (s, BGP_OPEN_OPT_CAP);
959 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
960 stream_putc (s, CAPABILITY_CODE_MP);
961 stream_putc (s, CAPABILITY_CODE_MP_LEN);
962 stream_putw (s, AFI_IP);
963 stream_putc (s, 0);
964 stream_putc (s, SAFI_UNICAST);
965 }
966 /* IPv4 multicast. */
967 if (peer->afc[AFI_IP][SAFI_MULTICAST])
968 {
969 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
970 stream_putc (s, BGP_OPEN_OPT_CAP);
971 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
972 stream_putc (s, CAPABILITY_CODE_MP);
973 stream_putc (s, CAPABILITY_CODE_MP_LEN);
974 stream_putw (s, AFI_IP);
975 stream_putc (s, 0);
976 stream_putc (s, SAFI_MULTICAST);
977 }
978 /* IPv4 VPN */
979 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
980 {
981 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
982 stream_putc (s, BGP_OPEN_OPT_CAP);
983 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
984 stream_putc (s, CAPABILITY_CODE_MP);
985 stream_putc (s, CAPABILITY_CODE_MP_LEN);
986 stream_putw (s, AFI_IP);
987 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400988 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000989 }
990#ifdef HAVE_IPV6
991 /* IPv6 unicast. */
992 if (peer->afc[AFI_IP6][SAFI_UNICAST])
993 {
994 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
995 stream_putc (s, BGP_OPEN_OPT_CAP);
996 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
997 stream_putc (s, CAPABILITY_CODE_MP);
998 stream_putc (s, CAPABILITY_CODE_MP_LEN);
999 stream_putw (s, AFI_IP6);
1000 stream_putc (s, 0);
1001 stream_putc (s, SAFI_UNICAST);
1002 }
1003 /* IPv6 multicast. */
1004 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1005 {
1006 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
1007 stream_putc (s, BGP_OPEN_OPT_CAP);
1008 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1009 stream_putc (s, CAPABILITY_CODE_MP);
1010 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1011 stream_putw (s, AFI_IP6);
1012 stream_putc (s, 0);
1013 stream_putc (s, SAFI_MULTICAST);
1014 }
1015#endif /* HAVE_IPV6 */
1016
1017 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001018 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1019 stream_putc (s, BGP_OPEN_OPT_CAP);
1020 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1021 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1022 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1023 stream_putc (s, BGP_OPEN_OPT_CAP);
1024 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1025 stream_putc (s, CAPABILITY_CODE_REFRESH);
1026 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001027
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001028 /* AS4 */
1029 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1030 stream_putc (s, BGP_OPEN_OPT_CAP);
1031 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1032 stream_putc (s, CAPABILITY_CODE_AS4);
1033 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1034 if ( peer->change_local_as )
1035 local_as = peer->change_local_as;
1036 else
1037 local_as = peer->local_as;
1038 stream_putl (s, local_as );
1039
paul718e3742002-12-13 20:15:29 +00001040 /* ORF capability. */
1041 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1042 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1043 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1044 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1045 {
1046 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1047 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1048 }
1049
1050 /* Dynamic capability. */
1051 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1052 {
1053 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1054 stream_putc (s, BGP_OPEN_OPT_CAP);
1055 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1056 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1057 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1058 }
1059
Vipin Kumardd49eb12014-09-30 14:36:38 -07001060 /* Sending base graceful-restart capability irrespective of the config */
1061 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1062 stream_putc (s, BGP_OPEN_OPT_CAP);
1063 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1064 stream_putc (s, 0); /* Capability Length */
1065 stream_putc (s, CAPABILITY_CODE_RESTART);
1066 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1067 stream_putc (s, 0);
1068 restart_time = peer->bgp->restart_time;
1069 if (peer->bgp->t_startup)
1070 {
1071 SET_FLAG (restart_time, RESTART_R_BIT);
1072 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1073 }
1074 stream_putw (s, restart_time);
1075
1076 /* Send address-family specific graceful-restart capability only when GR config
1077 is present */
hasso538621f2004-05-21 09:31:30 +00001078 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1079 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001080 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1081 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1082 if (peer->afc[afi][safi])
1083 {
1084 stream_putw (s, afi);
1085 stream_putc (s, safi);
1086 stream_putc (s, 0); //Forwarding is not retained as of now.
1087 }
1088 }
1089
1090 /* Total Graceful restart capability Len. */
1091 len = stream_get_endp (s) - rcapp - 1;
1092 stream_putc_at (s, rcapp, len);
1093
1094 /* Total Capability Len. */
1095 len = stream_get_endp (s) - capp - 1;
1096 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001097
paul718e3742002-12-13 20:15:29 +00001098 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001099 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001100 stream_putc_at (s, cp, len);
1101}