blob: 302e4ce5da66baa6aa96c393d2f3b69e1bebf5e4 [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]
Lou Berger9da04bc2016-01-12 13:41:55 -0500845 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
846 && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +0000847 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800848 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
849 "overlap with received MP capabilities",
850 peer->host);
paul718e3742002-12-13 20:15:29 +0000851
852 if (error != error_data)
853
854 bgp_notify_send_with_data (peer,
855 BGP_NOTIFY_OPEN_ERR,
856 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
857 error_data, error - error_data);
858 else
859 bgp_notify_send (peer,
860 BGP_NOTIFY_OPEN_ERR,
861 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
862 return -1;
863 }
864 }
865 return 0;
866}
867
paul94f2b392005-06-28 12:44:16 +0000868static void
paul718e3742002-12-13 20:15:29 +0000869bgp_open_capability_orf (struct stream *s, struct peer *peer,
870 afi_t afi, safi_t safi, u_char code)
871{
872 u_char cap_len;
873 u_char orf_len;
874 unsigned long capp;
875 unsigned long orfp;
876 unsigned long numberp;
877 int number_of_orfs = 0;
878
879 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400880 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000881
882 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000883 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000884 stream_putc (s, 0); /* Capability Length */
885 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000886 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000887 stream_putc (s, 0); /* ORF Length */
888 stream_putw (s, afi);
889 stream_putc (s, 0);
890 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000891 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000892 stream_putc (s, 0); /* Number of ORFs */
893
894 /* Address Prefix ORF */
895 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
896 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
897 {
898 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
899 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
900
901 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
902 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
903 {
904 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
905 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
906 stream_putc (s, ORF_MODE_BOTH);
907 }
908 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
909 {
910 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
911 stream_putc (s, ORF_MODE_SEND);
912 }
913 else
914 {
915 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
916 stream_putc (s, ORF_MODE_RECEIVE);
917 }
918 number_of_orfs++;
919 }
920
921 /* Total Number of ORFs. */
922 stream_putc_at (s, numberp, number_of_orfs);
923
924 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000925 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000926 stream_putc_at (s, orfp, orf_len);
927
928 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000929 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000930 stream_putc_at (s, capp, cap_len);
931}
932
933/* Fill in capability open option to the packet. */
934void
935bgp_open_capability (struct stream *s, struct peer *peer)
936{
937 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700938 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000939 afi_t afi;
940 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000941 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700942 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000943
944 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000945 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000946
947 /* Opt Parm Len. */
948 stream_putc (s, 0);
949
950 /* Do not send capability. */
951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
952 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
953 return;
954
paul718e3742002-12-13 20:15:29 +0000955 /* IPv4 unicast. */
956 if (peer->afc[AFI_IP][SAFI_UNICAST])
957 {
958 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
959 stream_putc (s, BGP_OPEN_OPT_CAP);
960 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
961 stream_putc (s, CAPABILITY_CODE_MP);
962 stream_putc (s, CAPABILITY_CODE_MP_LEN);
963 stream_putw (s, AFI_IP);
964 stream_putc (s, 0);
965 stream_putc (s, SAFI_UNICAST);
966 }
967 /* IPv4 multicast. */
968 if (peer->afc[AFI_IP][SAFI_MULTICAST])
969 {
970 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
971 stream_putc (s, BGP_OPEN_OPT_CAP);
972 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
973 stream_putc (s, CAPABILITY_CODE_MP);
974 stream_putc (s, CAPABILITY_CODE_MP_LEN);
975 stream_putw (s, AFI_IP);
976 stream_putc (s, 0);
977 stream_putc (s, SAFI_MULTICAST);
978 }
979 /* IPv4 VPN */
980 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
981 {
982 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
983 stream_putc (s, BGP_OPEN_OPT_CAP);
984 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
985 stream_putc (s, CAPABILITY_CODE_MP);
986 stream_putc (s, CAPABILITY_CODE_MP_LEN);
987 stream_putw (s, AFI_IP);
988 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400989 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000990 }
991#ifdef HAVE_IPV6
992 /* IPv6 unicast. */
993 if (peer->afc[AFI_IP6][SAFI_UNICAST])
994 {
995 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
996 stream_putc (s, BGP_OPEN_OPT_CAP);
997 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
998 stream_putc (s, CAPABILITY_CODE_MP);
999 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1000 stream_putw (s, AFI_IP6);
1001 stream_putc (s, 0);
1002 stream_putc (s, SAFI_UNICAST);
1003 }
1004 /* IPv6 multicast. */
1005 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1006 {
1007 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
1008 stream_putc (s, BGP_OPEN_OPT_CAP);
1009 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1010 stream_putc (s, CAPABILITY_CODE_MP);
1011 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1012 stream_putw (s, AFI_IP6);
1013 stream_putc (s, 0);
1014 stream_putc (s, SAFI_MULTICAST);
1015 }
Lou Berger9da04bc2016-01-12 13:41:55 -05001016 /* IPv6 VPN. */
1017 if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
1018 {
1019 peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1;
1020 stream_putc (s, BGP_OPEN_OPT_CAP);
1021 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1022 stream_putc (s, CAPABILITY_CODE_MP);
1023 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1024 stream_putw (s, AFI_IP6);
1025 stream_putc (s, 0);
1026 stream_putc (s, SAFI_MPLS_LABELED_VPN);
1027 }
paul718e3742002-12-13 20:15:29 +00001028#endif /* HAVE_IPV6 */
1029
1030 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001031 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1032 stream_putc (s, BGP_OPEN_OPT_CAP);
1033 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1034 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1035 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1036 stream_putc (s, BGP_OPEN_OPT_CAP);
1037 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1038 stream_putc (s, CAPABILITY_CODE_REFRESH);
1039 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001040
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001041 /* AS4 */
1042 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1043 stream_putc (s, BGP_OPEN_OPT_CAP);
1044 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1045 stream_putc (s, CAPABILITY_CODE_AS4);
1046 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1047 if ( peer->change_local_as )
1048 local_as = peer->change_local_as;
1049 else
1050 local_as = peer->local_as;
1051 stream_putl (s, local_as );
1052
paul718e3742002-12-13 20:15:29 +00001053 /* ORF capability. */
1054 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1055 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1056 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1057 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1058 {
1059 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1060 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1061 }
1062
1063 /* Dynamic capability. */
1064 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1065 {
1066 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1067 stream_putc (s, BGP_OPEN_OPT_CAP);
1068 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1069 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1070 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1071 }
1072
Vipin Kumardd49eb12014-09-30 14:36:38 -07001073 /* Sending base graceful-restart capability irrespective of the config */
1074 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1075 stream_putc (s, BGP_OPEN_OPT_CAP);
1076 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1077 stream_putc (s, 0); /* Capability Length */
1078 stream_putc (s, CAPABILITY_CODE_RESTART);
1079 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1080 stream_putc (s, 0);
1081 restart_time = peer->bgp->restart_time;
1082 if (peer->bgp->t_startup)
1083 {
1084 SET_FLAG (restart_time, RESTART_R_BIT);
1085 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1086 }
1087 stream_putw (s, restart_time);
1088
1089 /* Send address-family specific graceful-restart capability only when GR config
1090 is present */
hasso538621f2004-05-21 09:31:30 +00001091 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1092 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001093 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1094 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1095 if (peer->afc[afi][safi])
1096 {
1097 stream_putw (s, afi);
1098 stream_putc (s, safi);
1099 stream_putc (s, 0); //Forwarding is not retained as of now.
1100 }
1101 }
1102
1103 /* Total Graceful restart capability Len. */
1104 len = stream_get_endp (s) - rcapp - 1;
1105 stream_putc_at (s, rcapp, len);
1106
1107 /* Total Capability Len. */
1108 len = stream_get_endp (s) - capp - 1;
1109 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001110
paul718e3742002-12-13 20:15:29 +00001111 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001112 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001113 stream_putc_at (s, cp, len);
1114}