blob: 7b8b6577e078b1cd0eb10e258acfe1f0e4287825 [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;
Lou Berger298cc2f2016-01-12 13:42:02 -0500100 case SAFI_ENCAP:
101 vty_out (vty, "SAFI ENCAP");
102 break;
paul718e3742002-12-13 20:15:29 +0000103 default:
Paul Jakma6d582722007-08-06 15:21:45 +0000104 vty_out (vty, "SAFI Unknown %d ", mpc.safi);
paul718e3742002-12-13 20:15:29 +0000105 break;
106 }
107 vty_out (vty, "%s", VTY_NEWLINE);
108 }
Paul Jakma6d582722007-08-06 15:21:45 +0000109 else if (hdr->code >= 128)
paul718e3742002-12-13 20:15:29 +0000110 vty_out (vty, " Capability error: vendor specific capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000111 hdr->code);
paul718e3742002-12-13 20:15:29 +0000112 else
113 vty_out (vty, " Capability error: unknown capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000114 hdr->code);
paul718e3742002-12-13 20:15:29 +0000115
Paul Jakma6d582722007-08-06 15:21:45 +0000116 pnt += hdr->length + 2;
paul718e3742002-12-13 20:15:29 +0000117 }
118}
119
Paul Jakma6d582722007-08-06 15:21:45 +0000120static void
121bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
122{
123 mpc->afi = stream_getw (s);
124 mpc->reserved = stream_getc (s);
125 mpc->safi = stream_getc (s);
126}
127
128int
129bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
130{
Paul Jakma6d582722007-08-06 15:21:45 +0000131 switch (afi)
132 {
Donald Sharpf3cfc462016-01-07 09:33:28 -0500133 case AFI_IP:
134 case AFI_IP6:
135 switch (*safi)
136 {
137 /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
138 case SAFI_MPLS_LABELED_VPN:
139 *safi = SAFI_MPLS_VPN;
140 case SAFI_UNICAST:
141 case SAFI_MULTICAST:
142 case SAFI_MPLS_VPN:
Lou Berger298cc2f2016-01-12 13:42:02 -0500143 case SAFI_ENCAP:
Donald Sharpf3cfc462016-01-07 09:33:28 -0500144 return 1;
145 }
146 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000147 }
Donald Sharpf3cfc462016-01-07 09:33:28 -0500148
Paul Jakma6d582722007-08-06 15:21:45 +0000149 zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
Donald Sharpf3cfc462016-01-07 09:33:28 -0500150
Paul Jakma6d582722007-08-06 15:21:45 +0000151 return 0;
152}
153
paul718e3742002-12-13 20:15:29 +0000154/* Set negotiated capability value. */
paul94f2b392005-06-28 12:44:16 +0000155static int
Paul Jakma6d582722007-08-06 15:21:45 +0000156bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
paul718e3742002-12-13 20:15:29 +0000157{
Paul Jakma6d582722007-08-06 15:21:45 +0000158 struct capability_mp_data mpc;
159 struct stream *s = BGP_INPUT (peer);
160
161 bgp_capability_mp_data (s, &mpc);
162
163 if (BGP_DEBUG (normal, NORMAL))
164 zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
165 peer->host, mpc.afi, mpc.safi);
166
167 if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
168 return -1;
169
170 /* Now safi remapped, and afi/safi are valid array indices */
171 peer->afc_recv[mpc.afi][mpc.safi] = 1;
172
173 if (peer->afc[mpc.afi][mpc.safi])
Paul Jakmae08286b2007-09-18 12:11:26 +0000174 peer->afc_nego[mpc.afi][mpc.safi] = 1;
Paul Jakma6d582722007-08-06 15:21:45 +0000175 else
176 return -1;
paul718e3742002-12-13 20:15:29 +0000177
178 return 0;
179}
180
paul94f2b392005-06-28 12:44:16 +0000181static void
paul718e3742002-12-13 20:15:29 +0000182bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
183 u_char type, u_char mode)
184{
185 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000186 zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
paul718e3742002-12-13 20:15:29 +0000187 peer->host, afi, safi, type, mode);
188}
189
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700190static const struct message orf_type_str[] =
paul718e3742002-12-13 20:15:29 +0000191{
Paul Jakma6d582722007-08-06 15:21:45 +0000192 { ORF_TYPE_PREFIX, "Prefixlist" },
193 { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
194};
Balaji.G837d16c2012-09-26 14:09:10 +0530195static const int orf_type_str_max = array_size(orf_type_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000196
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700197static const struct message orf_mode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000198{
199 { ORF_MODE_RECEIVE, "Receive" },
200 { ORF_MODE_SEND, "Send" },
201 { ORF_MODE_BOTH, "Both" },
202};
Balaji.G837d16c2012-09-26 14:09:10 +0530203static const int orf_mode_str_max = array_size(orf_mode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000204
205static int
206bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
207{
208 struct stream *s = BGP_INPUT (peer);
209 struct capability_orf_entry entry;
210 afi_t afi;
211 safi_t safi;
paul718e3742002-12-13 20:15:29 +0000212 u_char type;
213 u_char mode;
214 u_int16_t sm_cap = 0; /* capability send-mode receive */
215 u_int16_t rm_cap = 0; /* capability receive-mode receive */
216 int i;
217
Paul Jakma6d582722007-08-06 15:21:45 +0000218 /* ORF Entry header */
219 bgp_capability_mp_data (s, &entry.mpc);
220 entry.num = stream_getc (s);
221 afi = entry.mpc.afi;
222 safi = entry.mpc.safi;
223
paul718e3742002-12-13 20:15:29 +0000224 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma6d582722007-08-06 15:21:45 +0000225 zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
226 peer->host, entry.mpc.afi, entry.mpc.safi);
paul718e3742002-12-13 20:15:29 +0000227
228 /* Check AFI and SAFI. */
Paul Jakma6d582722007-08-06 15:21:45 +0000229 if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
paul718e3742002-12-13 20:15:29 +0000230 {
Paul Jakma6d582722007-08-06 15:21:45 +0000231 zlog_info ("%s Addr-family %d/%d not supported."
232 " Ignoring the ORF capability",
233 peer->host, entry.mpc.afi, entry.mpc.safi);
234 return 0;
235 }
236
237 /* validate number field */
Donald Sharpf3cfc462016-01-07 09:33:28 -0500238 if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length)
Paul Jakma6d582722007-08-06 15:21:45 +0000239 {
240 zlog_info ("%s ORF Capability entry length error,"
241 " Cap length %u, num %u",
242 peer->host, hdr->length, entry.num);
Paul Jakma68ec4242015-11-25 17:14:34 +0000243 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000244 return -1;
245 }
246
Paul Jakma6d582722007-08-06 15:21:45 +0000247 for (i = 0 ; i < entry.num ; i++)
paul718e3742002-12-13 20:15:29 +0000248 {
Paul Jakma6d582722007-08-06 15:21:45 +0000249 type = stream_getc(s);
250 mode = stream_getc(s);
251
paul718e3742002-12-13 20:15:29 +0000252 /* ORF Mode error check */
Paul Jakma6d582722007-08-06 15:21:45 +0000253 switch (mode)
254 {
255 case ORF_MODE_BOTH:
256 case ORF_MODE_SEND:
257 case ORF_MODE_RECEIVE:
258 break;
259 default:
260 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
261 continue;
paul718e3742002-12-13 20:15:29 +0000262 }
Paul Jakma6d582722007-08-06 15:21:45 +0000263 /* ORF Type and afi/safi error checks */
264 /* capcode versus type */
265 switch (hdr->code)
266 {
267 case CAPABILITY_CODE_ORF:
268 switch (type)
269 {
270 case ORF_TYPE_PREFIX:
271 break;
272 default:
273 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
274 continue;
275 }
276 break;
277 case CAPABILITY_CODE_ORF_OLD:
278 switch (type)
279 {
280 case ORF_TYPE_PREFIX_OLD:
281 break;
282 default:
283 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
284 continue;
285 }
286 break;
287 default:
288 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
289 continue;
290 }
291
292 /* AFI vs SAFI */
293 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
294 || (afi == AFI_IP && safi == SAFI_MULTICAST)
295 || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
296 {
297 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
298 continue;
299 }
300
301 if (BGP_DEBUG (normal, NORMAL))
302 zlog_debug ("%s OPEN has %s ORF capability"
303 " as %s for afi/safi: %d/%d",
304 peer->host, LOOKUP (orf_type_str, type),
305 LOOKUP (orf_mode_str, mode),
306 entry.mpc.afi, safi);
paul718e3742002-12-13 20:15:29 +0000307
Paul Jakma6d582722007-08-06 15:21:45 +0000308 if (hdr->code == CAPABILITY_CODE_ORF)
paul718e3742002-12-13 20:15:29 +0000309 {
Paul Jakma6d582722007-08-06 15:21:45 +0000310 sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
311 rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
paul718e3742002-12-13 20:15:29 +0000312 }
Paul Jakma6d582722007-08-06 15:21:45 +0000313 else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
paul718e3742002-12-13 20:15:29 +0000314 {
Paul Jakma6d582722007-08-06 15:21:45 +0000315 sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
316 rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
paul718e3742002-12-13 20:15:29 +0000317 }
318 else
319 {
320 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
321 continue;
322 }
323
324 switch (mode)
325 {
326 case ORF_MODE_BOTH:
327 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
328 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
329 break;
330 case ORF_MODE_SEND:
331 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
332 break;
333 case ORF_MODE_RECEIVE:
334 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
335 break;
336 }
337 }
338 return 0;
339}
340
paul94f2b392005-06-28 12:44:16 +0000341static int
Paul Jakma6d582722007-08-06 15:21:45 +0000342bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
343{
344 struct stream *s = BGP_INPUT (peer);
345 u_int16_t restart_flag_time;
Paul Jakma6d582722007-08-06 15:21:45 +0000346 size_t end = stream_get_getp (s) + caphdr->length;
347
348 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
349 restart_flag_time = stream_getw(s);
350 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
Paul Jakmaec98d902014-10-14 11:14:06 +0100351 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
352
Paul Jakma6d582722007-08-06 15:21:45 +0000353 UNSET_FLAG (restart_flag_time, 0xF000);
354 peer->v_gr_restart = restart_flag_time;
355
356 if (BGP_DEBUG (normal, NORMAL))
357 {
358 zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
359 zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
Paul Jakmaec98d902014-10-14 11:14:06 +0100360 peer->host,
361 CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " "
362 : " not ",
Paul Jakma6d582722007-08-06 15:21:45 +0000363 peer->v_gr_restart);
364 }
365
Peter Pentchev21cc7692011-09-12 16:30:31 +0400366 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000367 {
368 afi_t afi = stream_getw (s);
369 safi_t safi = stream_getc (s);
370 u_char flag = stream_getc (s);
371
372 if (!bgp_afi_safi_valid_indices (afi, &safi))
373 {
374 if (BGP_DEBUG (normal, NORMAL))
375 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
376 " Ignore the Graceful Restart capability",
377 peer->host, afi, safi);
378 }
379 else if (!peer->afc[afi][safi])
380 {
381 if (BGP_DEBUG (normal, NORMAL))
382 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
383 " Ignore the Graceful Restart capability",
384 peer->host, afi, safi);
385 }
386 else
387 {
388 if (BGP_DEBUG (normal, NORMAL))
389 zlog_debug ("%s Address family %s is%spreserved", peer->host,
390 afi_safi_print (afi, safi),
391 CHECK_FLAG (peer->af_cap[afi][safi],
392 PEER_CAP_RESTART_AF_PRESERVE_RCV)
393 ? " " : " not ");
394
395 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
396 if (CHECK_FLAG (flag, RESTART_F_BIT))
397 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
398
399 }
400 }
401 return 0;
402}
403
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000404static as_t
405bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
406{
Paul Jakma58617392012-01-09 20:59:26 +0000407 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
408
409 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
410 {
411 zlog_err ("%s AS4 capability has incorrect data length %d",
412 peer->host, hdr->length);
413 return 0;
414 }
415
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000416 as_t as4 = stream_getl (BGP_INPUT(peer));
417
418 if (BGP_DEBUG (as4, AS4))
419 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
420 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000421 return as4;
422}
423
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700424static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000425{
Paul Jakma6d582722007-08-06 15:21:45 +0000426 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
427 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
428 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
429 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
430 { CAPABILITY_CODE_AS4, "4-octet AS number" },
431 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
432 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
433 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
434};
Balaji.G837d16c2012-09-26 14:09:10 +0530435static const int capcode_str_max = array_size(capcode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000436
437/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700438static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000439{
Donald Sharpf3cfc462016-01-07 09:33:28 -0500440 [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000441 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500442 [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
Lou Berger7748fdc2016-02-10 14:24:00 +0000443 [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000444 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
445 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
446 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500447 [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000448};
449
Paul Jakma4078f2e2015-11-25 17:14:35 +0000450/* value the capability must be a multiple of.
451 * 0-data capabilities won't be checked against this.
452 * Other capabilities whose data doesn't fall on convenient boundaries for this
453 * table should be set to 1.
454 */
455static const size_t cap_modsizes[] =
456{
457 [CAPABILITY_CODE_MP] = 4,
458 [CAPABILITY_CODE_REFRESH] = 1,
459 [CAPABILITY_CODE_ORF] = 1,
460 [CAPABILITY_CODE_RESTART] = 1,
461 [CAPABILITY_CODE_AS4] = 4,
462 [CAPABILITY_CODE_DYNAMIC] = 1,
463 [CAPABILITY_CODE_REFRESH_OLD] = 1,
464 [CAPABILITY_CODE_ORF_OLD] = 1,
465};
466
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800467/**
468 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000469 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800470 *
471 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
472 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000473 */
474static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800475bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
476 u_char **error)
paul718e3742002-12-13 20:15:29 +0000477{
478 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000479 struct stream *s = BGP_INPUT (peer);
480 size_t end = stream_get_getp (s) + length;
481
482 assert (STREAM_READABLE (s) >= length);
483
484 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000485 {
Paul Jakma6d582722007-08-06 15:21:45 +0000486 size_t start;
487 u_char *sp = stream_pnt (s);
488 struct capability_header caphdr;
489
paul718e3742002-12-13 20:15:29 +0000490 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000491 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000492 {
Paul Jakma6d582722007-08-06 15:21:45 +0000493 zlog_info ("%s Capability length error (< header)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000494 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000495 return -1;
496 }
Paul Jakma6d582722007-08-06 15:21:45 +0000497
498 caphdr.code = stream_getc (s);
499 caphdr.length = stream_getc (s);
500 start = stream_get_getp (s);
501
502 /* Capability length check sanity check. */
503 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000504 {
Paul Jakma6d582722007-08-06 15:21:45 +0000505 zlog_info ("%s Capability length error (< length)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000506 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000507 return -1;
508 }
Paul Jakma6d582722007-08-06 15:21:45 +0000509
510 if (BGP_DEBUG (normal, NORMAL))
511 zlog_debug ("%s OPEN has %s capability (%u), length %u",
512 peer->host,
513 LOOKUP (capcode_str, caphdr.code),
514 caphdr.code, caphdr.length);
515
516 /* Length sanity check, type-specific, for known capabilities */
517 switch (caphdr.code)
518 {
519 case CAPABILITY_CODE_MP:
520 case CAPABILITY_CODE_REFRESH:
521 case CAPABILITY_CODE_REFRESH_OLD:
522 case CAPABILITY_CODE_ORF:
523 case CAPABILITY_CODE_ORF_OLD:
524 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000525 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000526 case CAPABILITY_CODE_DYNAMIC:
527 /* Check length. */
528 if (caphdr.length < cap_minsizes[caphdr.code])
529 {
530 zlog_info ("%s %s Capability length error: got %u,"
531 " expected at least %u",
532 peer->host,
533 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700534 caphdr.length,
535 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma68ec4242015-11-25 17:14:34 +0000536 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
537 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma6d582722007-08-06 15:21:45 +0000538 return -1;
539 }
Paul Jakma4078f2e2015-11-25 17:14:35 +0000540 if (caphdr.length
541 && caphdr.length % cap_modsizes[caphdr.code] != 0)
542 {
543 zlog_info ("%s %s Capability length error: got %u,"
544 " expected a multiple of %u",
545 peer->host,
546 LOOKUP (capcode_str, caphdr.code),
547 caphdr.length,
548 (unsigned) cap_modsizes[caphdr.code]);
549 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
550 BGP_NOTIFY_OPEN_UNSPECIFIC);
551 return -1;
552 }
Paul Jakma6d582722007-08-06 15:21:45 +0000553 /* we deliberately ignore unknown codes, see below */
554 default:
555 break;
556 }
557
558 switch (caphdr.code)
559 {
560 case CAPABILITY_CODE_MP:
561 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800562 *mp_capability = 1;
563
Paul Jakma6d582722007-08-06 15:21:45 +0000564 /* Ignore capability when override-capability is set. */
565 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
566 {
567 /* Set negotiated value. */
568 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000569
Paul Jakma6d582722007-08-06 15:21:45 +0000570 /* Unsupported Capability. */
571 if (ret < 0)
572 {
573 /* Store return data. */
574 memcpy (*error, sp, caphdr.length + 2);
575 *error += caphdr.length + 2;
576 }
577 }
578 }
579 break;
580 case CAPABILITY_CODE_REFRESH:
581 case CAPABILITY_CODE_REFRESH_OLD:
582 {
583 /* BGP refresh capability */
584 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
585 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
586 else
587 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
588 }
589 break;
590 case CAPABILITY_CODE_ORF:
591 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400592 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000593 return -1;
594 break;
595 case CAPABILITY_CODE_RESTART:
596 if (bgp_capability_restart (peer, &caphdr))
597 return -1;
598 break;
599 case CAPABILITY_CODE_DYNAMIC:
600 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
601 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000602 case CAPABILITY_CODE_AS4:
603 /* Already handled as a special-case parsing of the capabilities
604 * at the beginning of OPEN processing. So we care not a jot
605 * for the value really, only error case.
606 */
607 if (!bgp_capability_as4 (peer, &caphdr))
608 return -1;
609 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000610 default:
611 if (caphdr.code > 128)
612 {
613 /* We don't send Notification for unknown vendor specific
614 capabilities. It seems reasonable for now... */
615 zlog_warn ("%s Vendor specific capability %d",
616 peer->host, caphdr.code);
617 }
618 else
619 {
620 zlog_warn ("%s unrecognized capability code: %d - ignored",
621 peer->host, caphdr.code);
622 memcpy (*error, sp, caphdr.length + 2);
623 *error += caphdr.length + 2;
624 }
625 }
626 if (stream_get_getp(s) != (start + caphdr.length))
627 {
628 if (stream_get_getp(s) > (start + caphdr.length))
629 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
630 peer->host, LOOKUP (capcode_str, caphdr.code),
631 caphdr.length);
632 stream_set_getp (s, start + caphdr.length);
633 }
paul718e3742002-12-13 20:15:29 +0000634 }
635 return 0;
636}
637
paul94f2b392005-06-28 12:44:16 +0000638static int
Paul Jakma6d582722007-08-06 15:21:45 +0000639bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000640{
641 bgp_notify_send (peer,
642 BGP_NOTIFY_OPEN_ERR,
643 BGP_NOTIFY_OPEN_AUTH_FAILURE);
644 return -1;
645}
646
paul94f2b392005-06-28 12:44:16 +0000647static int
paul718e3742002-12-13 20:15:29 +0000648strict_capability_same (struct peer *peer)
649{
650 int i, j;
651
652 for (i = AFI_IP; i < AFI_MAX; i++)
653 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
654 if (peer->afc[i][j] != peer->afc_nego[i][j])
655 return 0;
656 return 1;
657}
658
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000659/* peek into option, stores ASN to *as4 if the AS4 capability was found.
660 * Returns 0 if no as4 found, as4cap value otherwise.
661 */
662as_t
663peek_for_as4_capability (struct peer *peer, u_char length)
664{
665 struct stream *s = BGP_INPUT (peer);
666 size_t orig_getp = stream_get_getp (s);
667 size_t end = orig_getp + length;
668 as_t as4 = 0;
669
670 /* The full capability parser will better flag the error.. */
671 if (STREAM_READABLE(s) < length)
672 return 0;
673
674 if (BGP_DEBUG (as4, AS4))
675 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
676 " peeking for as4",
677 peer->host, length);
678 /* the error cases we DONT handle, we ONLY try to read as4 out of
679 * correctly formatted options.
680 */
681 while (stream_get_getp(s) < end)
682 {
683 u_char opt_type;
684 u_char opt_length;
685
686 /* Check the length. */
687 if (stream_get_getp (s) + 2 > end)
688 goto end;
689
690 /* Fetch option type and length. */
691 opt_type = stream_getc (s);
692 opt_length = stream_getc (s);
693
694 /* Option length check. */
695 if (stream_get_getp (s) + opt_length > end)
696 goto end;
697
698 if (opt_type == BGP_OPEN_OPT_CAP)
699 {
700 unsigned long capd_start = stream_get_getp (s);
701 unsigned long capd_end = capd_start + opt_length;
702
703 assert (capd_end <= end);
704
705 while (stream_get_getp (s) < capd_end)
706 {
707 struct capability_header hdr;
708
709 if (stream_get_getp (s) + 2 > capd_end)
710 goto end;
711
712 hdr.code = stream_getc (s);
713 hdr.length = stream_getc (s);
714
715 if ((stream_get_getp(s) + hdr.length) > capd_end)
716 goto end;
717
718 if (hdr.code == CAPABILITY_CODE_AS4)
719 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000720 if (BGP_DEBUG (as4, AS4))
721 zlog_info ("[AS4] found AS4 capability, about to parse");
722 as4 = bgp_capability_as4 (peer, &hdr);
723
724 goto end;
725 }
726 stream_forward_getp (s, hdr.length);
727 }
728 }
729 }
730
731end:
732 stream_set_getp (s, orig_getp);
733 return as4;
734}
735
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800736/**
737 * Parse open option.
738 *
739 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
740 */
paul718e3742002-12-13 20:15:29 +0000741int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800742bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000743{
744 int ret;
paul718e3742002-12-13 20:15:29 +0000745 u_char *error;
746 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000747 struct stream *s = BGP_INPUT(peer);
748 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000749
750 ret = 0;
paul718e3742002-12-13 20:15:29 +0000751 error = error_data;
752
753 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000754 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000755 peer->host, length);
756
Paul Jakma6d582722007-08-06 15:21:45 +0000757 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000758 {
Paul Jakma6d582722007-08-06 15:21:45 +0000759 u_char opt_type;
760 u_char opt_length;
761
762 /* Must have at least an OPEN option header */
763 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000764 {
765 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000766 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
767 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000768 return -1;
769 }
770
771 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000772 opt_type = stream_getc (s);
773 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000774
775 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000776 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000777 {
778 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000779 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
780 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000781 return -1;
782 }
783
784 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000785 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000786 peer->host, opt_type,
787 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
788 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
789 opt_length);
790
791 switch (opt_type)
792 {
793 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000794 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000795 break;
796 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800797 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000798 break;
799 default:
800 bgp_notify_send (peer,
801 BGP_NOTIFY_OPEN_ERR,
802 BGP_NOTIFY_OPEN_UNSUP_PARAM);
803 ret = -1;
804 break;
805 }
806
807 /* Parse error. To accumulate all unsupported capability codes,
808 bgp_capability_parse does not return -1 when encounter
809 unsupported capability code. To detect that, please check
810 error and erro_data pointer, like below. */
811 if (ret < 0)
812 return -1;
paul718e3742002-12-13 20:15:29 +0000813 }
814
815 /* All OPEN option is parsed. Check capability when strict compare
816 flag is enabled.*/
817 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
818 {
819 /* If Unsupported Capability exists. */
820 if (error != error_data)
821 {
822 bgp_notify_send_with_data (peer,
823 BGP_NOTIFY_OPEN_ERR,
824 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
825 error_data, error - error_data);
826 return -1;
827 }
828
829 /* Check local capability does not negotiated with remote
830 peer. */
831 if (! strict_capability_same (peer))
832 {
833 bgp_notify_send (peer,
834 BGP_NOTIFY_OPEN_ERR,
835 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
836 return -1;
837 }
838 }
839
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800840 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000841 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800842 if (*mp_capability &&
843 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000844 {
845 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
846 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
847 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -0500848 && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +0000849 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -0500850 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -0500851 && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
852 && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +0000853 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800854 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
855 "overlap with received MP capabilities",
856 peer->host);
paul718e3742002-12-13 20:15:29 +0000857
858 if (error != error_data)
859
860 bgp_notify_send_with_data (peer,
861 BGP_NOTIFY_OPEN_ERR,
862 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
863 error_data, error - error_data);
864 else
865 bgp_notify_send (peer,
866 BGP_NOTIFY_OPEN_ERR,
867 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
868 return -1;
869 }
870 }
871 return 0;
872}
873
paul94f2b392005-06-28 12:44:16 +0000874static void
paul718e3742002-12-13 20:15:29 +0000875bgp_open_capability_orf (struct stream *s, struct peer *peer,
876 afi_t afi, safi_t safi, u_char code)
877{
878 u_char cap_len;
879 u_char orf_len;
880 unsigned long capp;
881 unsigned long orfp;
882 unsigned long numberp;
883 int number_of_orfs = 0;
884
885 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400886 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000887
888 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000889 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000890 stream_putc (s, 0); /* Capability Length */
891 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000892 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000893 stream_putc (s, 0); /* ORF Length */
894 stream_putw (s, afi);
895 stream_putc (s, 0);
896 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000897 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000898 stream_putc (s, 0); /* Number of ORFs */
899
900 /* Address Prefix ORF */
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 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
905 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
906
907 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
908 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
909 {
910 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
911 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
912 stream_putc (s, ORF_MODE_BOTH);
913 }
914 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
915 {
916 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
917 stream_putc (s, ORF_MODE_SEND);
918 }
919 else
920 {
921 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
922 stream_putc (s, ORF_MODE_RECEIVE);
923 }
924 number_of_orfs++;
925 }
926
927 /* Total Number of ORFs. */
928 stream_putc_at (s, numberp, number_of_orfs);
929
930 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000931 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000932 stream_putc_at (s, orfp, orf_len);
933
934 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000935 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000936 stream_putc_at (s, capp, cap_len);
937}
938
939/* Fill in capability open option to the packet. */
940void
941bgp_open_capability (struct stream *s, struct peer *peer)
942{
943 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700944 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000945 afi_t afi;
946 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000947 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700948 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000949
950 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000951 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000952
953 /* Opt Parm Len. */
954 stream_putc (s, 0);
955
956 /* Do not send capability. */
957 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
958 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
959 return;
960
paul718e3742002-12-13 20:15:29 +0000961 /* IPv4 unicast. */
962 if (peer->afc[AFI_IP][SAFI_UNICAST])
963 {
964 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
965 stream_putc (s, BGP_OPEN_OPT_CAP);
966 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
967 stream_putc (s, CAPABILITY_CODE_MP);
968 stream_putc (s, CAPABILITY_CODE_MP_LEN);
969 stream_putw (s, AFI_IP);
970 stream_putc (s, 0);
971 stream_putc (s, SAFI_UNICAST);
972 }
973 /* IPv4 multicast. */
974 if (peer->afc[AFI_IP][SAFI_MULTICAST])
975 {
976 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
977 stream_putc (s, BGP_OPEN_OPT_CAP);
978 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
979 stream_putc (s, CAPABILITY_CODE_MP);
980 stream_putc (s, CAPABILITY_CODE_MP_LEN);
981 stream_putw (s, AFI_IP);
982 stream_putc (s, 0);
983 stream_putc (s, SAFI_MULTICAST);
984 }
985 /* IPv4 VPN */
986 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
987 {
988 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
989 stream_putc (s, BGP_OPEN_OPT_CAP);
990 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
991 stream_putc (s, CAPABILITY_CODE_MP);
992 stream_putc (s, CAPABILITY_CODE_MP_LEN);
993 stream_putw (s, AFI_IP);
994 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400995 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000996 }
Lou Berger298cc2f2016-01-12 13:42:02 -0500997 /* ENCAP */
998 if (peer->afc[AFI_IP][SAFI_ENCAP])
999 {
1000 peer->afc_adv[AFI_IP][SAFI_ENCAP] = 1;
1001 stream_putc (s, BGP_OPEN_OPT_CAP);
1002 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1003 stream_putc (s, CAPABILITY_CODE_MP);
1004 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1005 stream_putw (s, AFI_IP);
1006 stream_putc (s, 0);
1007 stream_putc (s, SAFI_ENCAP);
1008 }
paul718e3742002-12-13 20:15:29 +00001009 /* IPv6 unicast. */
1010 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1011 {
1012 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
1013 stream_putc (s, BGP_OPEN_OPT_CAP);
1014 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1015 stream_putc (s, CAPABILITY_CODE_MP);
1016 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1017 stream_putw (s, AFI_IP6);
1018 stream_putc (s, 0);
1019 stream_putc (s, SAFI_UNICAST);
1020 }
1021 /* IPv6 multicast. */
1022 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1023 {
1024 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
1025 stream_putc (s, BGP_OPEN_OPT_CAP);
1026 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1027 stream_putc (s, CAPABILITY_CODE_MP);
1028 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1029 stream_putw (s, AFI_IP6);
1030 stream_putc (s, 0);
1031 stream_putc (s, SAFI_MULTICAST);
1032 }
Lou Berger9da04bc2016-01-12 13:41:55 -05001033 /* IPv6 VPN. */
1034 if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
1035 {
1036 peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1;
1037 stream_putc (s, BGP_OPEN_OPT_CAP);
1038 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1039 stream_putc (s, CAPABILITY_CODE_MP);
1040 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1041 stream_putw (s, AFI_IP6);
1042 stream_putc (s, 0);
1043 stream_putc (s, SAFI_MPLS_LABELED_VPN);
1044 }
Lou Berger298cc2f2016-01-12 13:42:02 -05001045 /* IPv6 ENCAP. */
1046 if (peer->afc[AFI_IP6][SAFI_ENCAP])
1047 {
1048 peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 1;
1049 stream_putc (s, BGP_OPEN_OPT_CAP);
1050 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1051 stream_putc (s, CAPABILITY_CODE_MP);
1052 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1053 stream_putw (s, AFI_IP6);
1054 stream_putc (s, 0);
1055 stream_putc (s, SAFI_ENCAP);
1056 }
paul718e3742002-12-13 20:15:29 +00001057
1058 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001059 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1060 stream_putc (s, BGP_OPEN_OPT_CAP);
1061 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1062 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1063 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1064 stream_putc (s, BGP_OPEN_OPT_CAP);
1065 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1066 stream_putc (s, CAPABILITY_CODE_REFRESH);
1067 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001068
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001069 /* AS4 */
1070 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1071 stream_putc (s, BGP_OPEN_OPT_CAP);
1072 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1073 stream_putc (s, CAPABILITY_CODE_AS4);
1074 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1075 if ( peer->change_local_as )
1076 local_as = peer->change_local_as;
1077 else
1078 local_as = peer->local_as;
1079 stream_putl (s, local_as );
1080
paul718e3742002-12-13 20:15:29 +00001081 /* ORF capability. */
1082 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1083 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1084 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1085 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1086 {
1087 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1088 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1089 }
1090
1091 /* Dynamic capability. */
1092 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1093 {
1094 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1095 stream_putc (s, BGP_OPEN_OPT_CAP);
1096 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1097 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1098 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1099 }
1100
Vipin Kumardd49eb12014-09-30 14:36:38 -07001101 /* Sending base graceful-restart capability irrespective of the config */
1102 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1103 stream_putc (s, BGP_OPEN_OPT_CAP);
1104 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1105 stream_putc (s, 0); /* Capability Length */
1106 stream_putc (s, CAPABILITY_CODE_RESTART);
1107 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1108 stream_putc (s, 0);
1109 restart_time = peer->bgp->restart_time;
1110 if (peer->bgp->t_startup)
1111 {
1112 SET_FLAG (restart_time, RESTART_R_BIT);
1113 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1114 }
1115 stream_putw (s, restart_time);
1116
1117 /* Send address-family specific graceful-restart capability only when GR config
1118 is present */
hasso538621f2004-05-21 09:31:30 +00001119 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1120 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001121 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1122 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1123 if (peer->afc[afi][safi])
1124 {
1125 stream_putw (s, afi);
1126 stream_putc (s, safi);
1127 stream_putc (s, 0); //Forwarding is not retained as of now.
1128 }
1129 }
1130
1131 /* Total Graceful restart capability Len. */
1132 len = stream_get_endp (s) - rcapp - 1;
1133 stream_putc_at (s, rcapp, len);
1134
1135 /* Total Capability Len. */
1136 len = stream_get_endp (s) - capp - 1;
1137 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001138
paul718e3742002-12-13 20:15:29 +00001139 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001140 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001141 stream_putc_at (s, cp, len);
1142}