blob: 280042306f303d4477b0a3f4e571be22a01fac91 [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 }
Paul Jakma7fa7acb2017-01-20 18:16:04 +0000146 case AFI_ETHER:
147 default:
Donald Sharpf3cfc462016-01-07 09:33:28 -0500148 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000149 }
Donald Sharpf3cfc462016-01-07 09:33:28 -0500150
Paul Jakma6d582722007-08-06 15:21:45 +0000151 zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
Donald Sharpf3cfc462016-01-07 09:33:28 -0500152
Paul Jakma6d582722007-08-06 15:21:45 +0000153 return 0;
154}
155
paul718e3742002-12-13 20:15:29 +0000156/* Set negotiated capability value. */
paul94f2b392005-06-28 12:44:16 +0000157static int
Paul Jakma6d582722007-08-06 15:21:45 +0000158bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
paul718e3742002-12-13 20:15:29 +0000159{
Paul Jakma6d582722007-08-06 15:21:45 +0000160 struct capability_mp_data mpc;
161 struct stream *s = BGP_INPUT (peer);
162
163 bgp_capability_mp_data (s, &mpc);
164
165 if (BGP_DEBUG (normal, NORMAL))
166 zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
167 peer->host, mpc.afi, mpc.safi);
168
169 if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
170 return -1;
171
172 /* Now safi remapped, and afi/safi are valid array indices */
173 peer->afc_recv[mpc.afi][mpc.safi] = 1;
174
175 if (peer->afc[mpc.afi][mpc.safi])
Paul Jakmae08286b2007-09-18 12:11:26 +0000176 peer->afc_nego[mpc.afi][mpc.safi] = 1;
Paul Jakma6d582722007-08-06 15:21:45 +0000177 else
178 return -1;
paul718e3742002-12-13 20:15:29 +0000179
180 return 0;
181}
182
paul94f2b392005-06-28 12:44:16 +0000183static void
paul718e3742002-12-13 20:15:29 +0000184bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
185 u_char type, u_char mode)
186{
187 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000188 zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
paul718e3742002-12-13 20:15:29 +0000189 peer->host, afi, safi, type, mode);
190}
191
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700192static const struct message orf_type_str[] =
paul718e3742002-12-13 20:15:29 +0000193{
Paul Jakma6d582722007-08-06 15:21:45 +0000194 { ORF_TYPE_PREFIX, "Prefixlist" },
195 { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
196};
Balaji.G837d16c2012-09-26 14:09:10 +0530197static const int orf_type_str_max = array_size(orf_type_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000198
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700199static const struct message orf_mode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000200{
201 { ORF_MODE_RECEIVE, "Receive" },
202 { ORF_MODE_SEND, "Send" },
203 { ORF_MODE_BOTH, "Both" },
204};
Balaji.G837d16c2012-09-26 14:09:10 +0530205static const int orf_mode_str_max = array_size(orf_mode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000206
207static int
208bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
209{
210 struct stream *s = BGP_INPUT (peer);
211 struct capability_orf_entry entry;
212 afi_t afi;
213 safi_t safi;
paul718e3742002-12-13 20:15:29 +0000214 u_char type;
215 u_char mode;
216 u_int16_t sm_cap = 0; /* capability send-mode receive */
217 u_int16_t rm_cap = 0; /* capability receive-mode receive */
218 int i;
219
Paul Jakma6d582722007-08-06 15:21:45 +0000220 /* ORF Entry header */
221 bgp_capability_mp_data (s, &entry.mpc);
222 entry.num = stream_getc (s);
223 afi = entry.mpc.afi;
224 safi = entry.mpc.safi;
225
paul718e3742002-12-13 20:15:29 +0000226 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma6d582722007-08-06 15:21:45 +0000227 zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
228 peer->host, entry.mpc.afi, entry.mpc.safi);
paul718e3742002-12-13 20:15:29 +0000229
230 /* Check AFI and SAFI. */
Paul Jakma6d582722007-08-06 15:21:45 +0000231 if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
paul718e3742002-12-13 20:15:29 +0000232 {
Paul Jakma6d582722007-08-06 15:21:45 +0000233 zlog_info ("%s Addr-family %d/%d not supported."
234 " Ignoring the ORF capability",
235 peer->host, entry.mpc.afi, entry.mpc.safi);
236 return 0;
237 }
238
239 /* validate number field */
Donald Sharpf3cfc462016-01-07 09:33:28 -0500240 if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length)
Paul Jakma6d582722007-08-06 15:21:45 +0000241 {
242 zlog_info ("%s ORF Capability entry length error,"
243 " Cap length %u, num %u",
244 peer->host, hdr->length, entry.num);
Paul Jakma68ec4242015-11-25 17:14:34 +0000245 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000246 return -1;
247 }
248
Paul Jakma6d582722007-08-06 15:21:45 +0000249 for (i = 0 ; i < entry.num ; i++)
paul718e3742002-12-13 20:15:29 +0000250 {
Paul Jakma6d582722007-08-06 15:21:45 +0000251 type = stream_getc(s);
252 mode = stream_getc(s);
253
paul718e3742002-12-13 20:15:29 +0000254 /* ORF Mode error check */
Paul Jakma6d582722007-08-06 15:21:45 +0000255 switch (mode)
256 {
257 case ORF_MODE_BOTH:
258 case ORF_MODE_SEND:
259 case ORF_MODE_RECEIVE:
260 break;
261 default:
262 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
263 continue;
paul718e3742002-12-13 20:15:29 +0000264 }
Paul Jakma6d582722007-08-06 15:21:45 +0000265 /* ORF Type and afi/safi error checks */
266 /* capcode versus type */
267 switch (hdr->code)
268 {
269 case CAPABILITY_CODE_ORF:
270 switch (type)
271 {
272 case ORF_TYPE_PREFIX:
273 break;
274 default:
275 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
276 continue;
277 }
278 break;
279 case CAPABILITY_CODE_ORF_OLD:
280 switch (type)
281 {
282 case ORF_TYPE_PREFIX_OLD:
283 break;
284 default:
285 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
286 continue;
287 }
288 break;
289 default:
290 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
291 continue;
292 }
293
294 /* AFI vs SAFI */
295 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
296 || (afi == AFI_IP && safi == SAFI_MULTICAST)
297 || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
298 {
299 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
300 continue;
301 }
302
303 if (BGP_DEBUG (normal, NORMAL))
304 zlog_debug ("%s OPEN has %s ORF capability"
305 " as %s for afi/safi: %d/%d",
306 peer->host, LOOKUP (orf_type_str, type),
307 LOOKUP (orf_mode_str, mode),
308 entry.mpc.afi, safi);
paul718e3742002-12-13 20:15:29 +0000309
Paul Jakma6d582722007-08-06 15:21:45 +0000310 if (hdr->code == CAPABILITY_CODE_ORF)
paul718e3742002-12-13 20:15:29 +0000311 {
Paul Jakma6d582722007-08-06 15:21:45 +0000312 sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
313 rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
paul718e3742002-12-13 20:15:29 +0000314 }
Paul Jakma6d582722007-08-06 15:21:45 +0000315 else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
paul718e3742002-12-13 20:15:29 +0000316 {
Paul Jakma6d582722007-08-06 15:21:45 +0000317 sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
318 rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
paul718e3742002-12-13 20:15:29 +0000319 }
320 else
321 {
322 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
323 continue;
324 }
325
326 switch (mode)
327 {
328 case ORF_MODE_BOTH:
329 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
330 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
331 break;
332 case ORF_MODE_SEND:
333 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
334 break;
335 case ORF_MODE_RECEIVE:
336 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
337 break;
338 }
339 }
340 return 0;
341}
342
paul94f2b392005-06-28 12:44:16 +0000343static int
Paul Jakma6d582722007-08-06 15:21:45 +0000344bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
345{
346 struct stream *s = BGP_INPUT (peer);
347 u_int16_t restart_flag_time;
Paul Jakma6d582722007-08-06 15:21:45 +0000348 size_t end = stream_get_getp (s) + caphdr->length;
349
350 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
351 restart_flag_time = stream_getw(s);
352 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
Paul Jakmaec98d902014-10-14 11:14:06 +0100353 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
354
Paul Jakma6d582722007-08-06 15:21:45 +0000355 UNSET_FLAG (restart_flag_time, 0xF000);
356 peer->v_gr_restart = restart_flag_time;
357
358 if (BGP_DEBUG (normal, NORMAL))
359 {
360 zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
361 zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
Paul Jakmaec98d902014-10-14 11:14:06 +0100362 peer->host,
363 CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " "
364 : " not ",
Paul Jakma6d582722007-08-06 15:21:45 +0000365 peer->v_gr_restart);
366 }
367
Peter Pentchev21cc7692011-09-12 16:30:31 +0400368 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000369 {
370 afi_t afi = stream_getw (s);
371 safi_t safi = stream_getc (s);
372 u_char flag = stream_getc (s);
373
374 if (!bgp_afi_safi_valid_indices (afi, &safi))
375 {
376 if (BGP_DEBUG (normal, NORMAL))
377 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
378 " Ignore the Graceful Restart capability",
379 peer->host, afi, safi);
380 }
381 else if (!peer->afc[afi][safi])
382 {
383 if (BGP_DEBUG (normal, NORMAL))
384 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
385 " Ignore the Graceful Restart capability",
386 peer->host, afi, safi);
387 }
388 else
389 {
390 if (BGP_DEBUG (normal, NORMAL))
391 zlog_debug ("%s Address family %s is%spreserved", peer->host,
392 afi_safi_print (afi, safi),
393 CHECK_FLAG (peer->af_cap[afi][safi],
394 PEER_CAP_RESTART_AF_PRESERVE_RCV)
395 ? " " : " not ");
396
397 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
398 if (CHECK_FLAG (flag, RESTART_F_BIT))
399 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
400
401 }
402 }
403 return 0;
404}
405
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000406static as_t
407bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
408{
Paul Jakma58617392012-01-09 20:59:26 +0000409 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
410
411 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
412 {
413 zlog_err ("%s AS4 capability has incorrect data length %d",
414 peer->host, hdr->length);
415 return 0;
416 }
417
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000418 as_t as4 = stream_getl (BGP_INPUT(peer));
419
420 if (BGP_DEBUG (as4, AS4))
421 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
422 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000423 return as4;
424}
425
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700426static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000427{
Paul Jakma6d582722007-08-06 15:21:45 +0000428 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
429 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
430 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
431 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
432 { CAPABILITY_CODE_AS4, "4-octet AS number" },
433 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
434 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
435 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
436};
Balaji.G837d16c2012-09-26 14:09:10 +0530437static const int capcode_str_max = array_size(capcode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000438
439/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700440static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000441{
Donald Sharpf3cfc462016-01-07 09:33:28 -0500442 [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000443 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500444 [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
Lou Berger7748fdc2016-02-10 14:24:00 +0000445 [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000446 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
447 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
448 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
Donald Sharpf3cfc462016-01-07 09:33:28 -0500449 [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
Paul Jakma6d582722007-08-06 15:21:45 +0000450};
451
Paul Jakma4078f2e2015-11-25 17:14:35 +0000452/* value the capability must be a multiple of.
453 * 0-data capabilities won't be checked against this.
454 * Other capabilities whose data doesn't fall on convenient boundaries for this
455 * table should be set to 1.
456 */
457static const size_t cap_modsizes[] =
458{
459 [CAPABILITY_CODE_MP] = 4,
460 [CAPABILITY_CODE_REFRESH] = 1,
461 [CAPABILITY_CODE_ORF] = 1,
462 [CAPABILITY_CODE_RESTART] = 1,
463 [CAPABILITY_CODE_AS4] = 4,
464 [CAPABILITY_CODE_DYNAMIC] = 1,
465 [CAPABILITY_CODE_REFRESH_OLD] = 1,
466 [CAPABILITY_CODE_ORF_OLD] = 1,
467};
468
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800469/**
470 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000471 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800472 *
473 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
474 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000475 */
476static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800477bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
478 u_char **error)
paul718e3742002-12-13 20:15:29 +0000479{
480 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000481 struct stream *s = BGP_INPUT (peer);
482 size_t end = stream_get_getp (s) + length;
483
484 assert (STREAM_READABLE (s) >= length);
485
486 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000487 {
Paul Jakma6d582722007-08-06 15:21:45 +0000488 size_t start;
489 u_char *sp = stream_pnt (s);
490 struct capability_header caphdr;
491
paul718e3742002-12-13 20:15:29 +0000492 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000493 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000494 {
Paul Jakma6d582722007-08-06 15:21:45 +0000495 zlog_info ("%s Capability length error (< header)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000496 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000497 return -1;
498 }
Paul Jakma6d582722007-08-06 15:21:45 +0000499
500 caphdr.code = stream_getc (s);
501 caphdr.length = stream_getc (s);
502 start = stream_get_getp (s);
503
504 /* Capability length check sanity check. */
505 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000506 {
Paul Jakma6d582722007-08-06 15:21:45 +0000507 zlog_info ("%s Capability length error (< length)", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000508 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000509 return -1;
510 }
Paul Jakma6d582722007-08-06 15:21:45 +0000511
512 if (BGP_DEBUG (normal, NORMAL))
513 zlog_debug ("%s OPEN has %s capability (%u), length %u",
514 peer->host,
515 LOOKUP (capcode_str, caphdr.code),
516 caphdr.code, caphdr.length);
517
518 /* Length sanity check, type-specific, for known capabilities */
519 switch (caphdr.code)
520 {
521 case CAPABILITY_CODE_MP:
522 case CAPABILITY_CODE_REFRESH:
523 case CAPABILITY_CODE_REFRESH_OLD:
524 case CAPABILITY_CODE_ORF:
525 case CAPABILITY_CODE_ORF_OLD:
526 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000527 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000528 case CAPABILITY_CODE_DYNAMIC:
529 /* Check length. */
530 if (caphdr.length < cap_minsizes[caphdr.code])
531 {
532 zlog_info ("%s %s Capability length error: got %u,"
533 " expected at least %u",
534 peer->host,
535 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700536 caphdr.length,
537 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma68ec4242015-11-25 17:14:34 +0000538 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
539 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma6d582722007-08-06 15:21:45 +0000540 return -1;
541 }
Paul Jakma4078f2e2015-11-25 17:14:35 +0000542 if (caphdr.length
543 && caphdr.length % cap_modsizes[caphdr.code] != 0)
544 {
545 zlog_info ("%s %s Capability length error: got %u,"
546 " expected a multiple of %u",
547 peer->host,
548 LOOKUP (capcode_str, caphdr.code),
549 caphdr.length,
550 (unsigned) cap_modsizes[caphdr.code]);
551 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
552 BGP_NOTIFY_OPEN_UNSPECIFIC);
553 return -1;
554 }
Paul Jakma6d582722007-08-06 15:21:45 +0000555 /* we deliberately ignore unknown codes, see below */
556 default:
557 break;
558 }
559
560 switch (caphdr.code)
561 {
562 case CAPABILITY_CODE_MP:
563 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800564 *mp_capability = 1;
565
Paul Jakma6d582722007-08-06 15:21:45 +0000566 /* Ignore capability when override-capability is set. */
567 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
568 {
569 /* Set negotiated value. */
570 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000571
Paul Jakma6d582722007-08-06 15:21:45 +0000572 /* Unsupported Capability. */
573 if (ret < 0)
574 {
575 /* Store return data. */
576 memcpy (*error, sp, caphdr.length + 2);
577 *error += caphdr.length + 2;
578 }
579 }
580 }
581 break;
582 case CAPABILITY_CODE_REFRESH:
583 case CAPABILITY_CODE_REFRESH_OLD:
584 {
585 /* BGP refresh capability */
586 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
587 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
588 else
589 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
590 }
591 break;
592 case CAPABILITY_CODE_ORF:
593 case CAPABILITY_CODE_ORF_OLD:
Denis Ovsienkofe9bb642012-04-19 20:34:13 +0400594 if (bgp_capability_orf_entry (peer, &caphdr))
Paul Jakma6d582722007-08-06 15:21:45 +0000595 return -1;
596 break;
597 case CAPABILITY_CODE_RESTART:
598 if (bgp_capability_restart (peer, &caphdr))
599 return -1;
600 break;
601 case CAPABILITY_CODE_DYNAMIC:
602 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
603 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000604 case CAPABILITY_CODE_AS4:
605 /* Already handled as a special-case parsing of the capabilities
606 * at the beginning of OPEN processing. So we care not a jot
607 * for the value really, only error case.
608 */
609 if (!bgp_capability_as4 (peer, &caphdr))
610 return -1;
611 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000612 default:
613 if (caphdr.code > 128)
614 {
615 /* We don't send Notification for unknown vendor specific
616 capabilities. It seems reasonable for now... */
617 zlog_warn ("%s Vendor specific capability %d",
618 peer->host, caphdr.code);
619 }
620 else
621 {
622 zlog_warn ("%s unrecognized capability code: %d - ignored",
623 peer->host, caphdr.code);
624 memcpy (*error, sp, caphdr.length + 2);
625 *error += caphdr.length + 2;
626 }
627 }
628 if (stream_get_getp(s) != (start + caphdr.length))
629 {
630 if (stream_get_getp(s) > (start + caphdr.length))
631 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
632 peer->host, LOOKUP (capcode_str, caphdr.code),
633 caphdr.length);
634 stream_set_getp (s, start + caphdr.length);
635 }
paul718e3742002-12-13 20:15:29 +0000636 }
637 return 0;
638}
639
paul94f2b392005-06-28 12:44:16 +0000640static int
Paul Jakma6d582722007-08-06 15:21:45 +0000641bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000642{
643 bgp_notify_send (peer,
644 BGP_NOTIFY_OPEN_ERR,
645 BGP_NOTIFY_OPEN_AUTH_FAILURE);
646 return -1;
647}
648
paul94f2b392005-06-28 12:44:16 +0000649static int
paul718e3742002-12-13 20:15:29 +0000650strict_capability_same (struct peer *peer)
651{
652 int i, j;
653
654 for (i = AFI_IP; i < AFI_MAX; i++)
655 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
656 if (peer->afc[i][j] != peer->afc_nego[i][j])
657 return 0;
658 return 1;
659}
660
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000661/* peek into option, stores ASN to *as4 if the AS4 capability was found.
662 * Returns 0 if no as4 found, as4cap value otherwise.
663 */
664as_t
665peek_for_as4_capability (struct peer *peer, u_char length)
666{
667 struct stream *s = BGP_INPUT (peer);
668 size_t orig_getp = stream_get_getp (s);
669 size_t end = orig_getp + length;
670 as_t as4 = 0;
671
672 /* The full capability parser will better flag the error.. */
673 if (STREAM_READABLE(s) < length)
674 return 0;
675
676 if (BGP_DEBUG (as4, AS4))
677 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
678 " peeking for as4",
679 peer->host, length);
680 /* the error cases we DONT handle, we ONLY try to read as4 out of
681 * correctly formatted options.
682 */
683 while (stream_get_getp(s) < end)
684 {
685 u_char opt_type;
686 u_char opt_length;
687
688 /* Check the length. */
689 if (stream_get_getp (s) + 2 > end)
690 goto end;
691
692 /* Fetch option type and length. */
693 opt_type = stream_getc (s);
694 opt_length = stream_getc (s);
695
696 /* Option length check. */
697 if (stream_get_getp (s) + opt_length > end)
698 goto end;
699
700 if (opt_type == BGP_OPEN_OPT_CAP)
701 {
702 unsigned long capd_start = stream_get_getp (s);
703 unsigned long capd_end = capd_start + opt_length;
704
705 assert (capd_end <= end);
706
707 while (stream_get_getp (s) < capd_end)
708 {
709 struct capability_header hdr;
710
711 if (stream_get_getp (s) + 2 > capd_end)
712 goto end;
713
714 hdr.code = stream_getc (s);
715 hdr.length = stream_getc (s);
716
717 if ((stream_get_getp(s) + hdr.length) > capd_end)
718 goto end;
719
720 if (hdr.code == CAPABILITY_CODE_AS4)
721 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000722 if (BGP_DEBUG (as4, AS4))
723 zlog_info ("[AS4] found AS4 capability, about to parse");
724 as4 = bgp_capability_as4 (peer, &hdr);
725
726 goto end;
727 }
728 stream_forward_getp (s, hdr.length);
729 }
730 }
731 }
732
733end:
734 stream_set_getp (s, orig_getp);
735 return as4;
736}
737
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800738/**
739 * Parse open option.
740 *
741 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
742 */
paul718e3742002-12-13 20:15:29 +0000743int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800744bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000745{
746 int ret;
paul718e3742002-12-13 20:15:29 +0000747 u_char *error;
748 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000749 struct stream *s = BGP_INPUT(peer);
750 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000751
752 ret = 0;
paul718e3742002-12-13 20:15:29 +0000753 error = error_data;
754
755 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000756 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000757 peer->host, length);
758
Paul Jakma6d582722007-08-06 15:21:45 +0000759 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000760 {
Paul Jakma6d582722007-08-06 15:21:45 +0000761 u_char opt_type;
762 u_char opt_length;
763
764 /* Must have at least an OPEN option header */
765 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000766 {
767 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000768 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
769 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000770 return -1;
771 }
772
773 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000774 opt_type = stream_getc (s);
775 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000776
777 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000778 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000779 {
780 zlog_info ("%s Option length error", peer->host);
Paul Jakma68ec4242015-11-25 17:14:34 +0000781 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
782 BGP_NOTIFY_OPEN_UNSPECIFIC);
paul718e3742002-12-13 20:15:29 +0000783 return -1;
784 }
785
786 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000787 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000788 peer->host, opt_type,
789 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
790 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
791 opt_length);
792
793 switch (opt_type)
794 {
795 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000796 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000797 break;
798 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800799 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000800 break;
801 default:
802 bgp_notify_send (peer,
803 BGP_NOTIFY_OPEN_ERR,
804 BGP_NOTIFY_OPEN_UNSUP_PARAM);
805 ret = -1;
806 break;
807 }
808
809 /* Parse error. To accumulate all unsupported capability codes,
810 bgp_capability_parse does not return -1 when encounter
811 unsupported capability code. To detect that, please check
812 error and erro_data pointer, like below. */
813 if (ret < 0)
814 return -1;
paul718e3742002-12-13 20:15:29 +0000815 }
816
817 /* All OPEN option is parsed. Check capability when strict compare
818 flag is enabled.*/
819 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
820 {
821 /* If Unsupported Capability exists. */
822 if (error != error_data)
823 {
824 bgp_notify_send_with_data (peer,
825 BGP_NOTIFY_OPEN_ERR,
826 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
827 error_data, error - error_data);
828 return -1;
829 }
830
831 /* Check local capability does not negotiated with remote
832 peer. */
833 if (! strict_capability_same (peer))
834 {
835 bgp_notify_send (peer,
836 BGP_NOTIFY_OPEN_ERR,
837 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
838 return -1;
839 }
840 }
841
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800842 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000843 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800844 if (*mp_capability &&
845 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000846 {
847 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
848 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
849 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -0500850 && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +0000851 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -0500852 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -0500853 && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
854 && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +0000855 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800856 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
857 "overlap with received MP capabilities",
858 peer->host);
paul718e3742002-12-13 20:15:29 +0000859
860 if (error != error_data)
861
862 bgp_notify_send_with_data (peer,
863 BGP_NOTIFY_OPEN_ERR,
864 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
865 error_data, error - error_data);
866 else
867 bgp_notify_send (peer,
868 BGP_NOTIFY_OPEN_ERR,
869 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
870 return -1;
871 }
872 }
873 return 0;
874}
875
paul94f2b392005-06-28 12:44:16 +0000876static void
paul718e3742002-12-13 20:15:29 +0000877bgp_open_capability_orf (struct stream *s, struct peer *peer,
878 afi_t afi, safi_t safi, u_char code)
879{
880 u_char cap_len;
881 u_char orf_len;
882 unsigned long capp;
883 unsigned long orfp;
884 unsigned long numberp;
885 int number_of_orfs = 0;
886
887 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400888 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000889
890 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000891 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000892 stream_putc (s, 0); /* Capability Length */
893 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000894 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000895 stream_putc (s, 0); /* ORF Length */
896 stream_putw (s, afi);
897 stream_putc (s, 0);
898 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000899 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000900 stream_putc (s, 0); /* Number of ORFs */
901
902 /* Address Prefix ORF */
903 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
904 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
905 {
906 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
907 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
908
909 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
910 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
911 {
912 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
913 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
914 stream_putc (s, ORF_MODE_BOTH);
915 }
916 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
917 {
918 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
919 stream_putc (s, ORF_MODE_SEND);
920 }
921 else
922 {
923 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
924 stream_putc (s, ORF_MODE_RECEIVE);
925 }
926 number_of_orfs++;
927 }
928
929 /* Total Number of ORFs. */
930 stream_putc_at (s, numberp, number_of_orfs);
931
932 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000933 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000934 stream_putc_at (s, orfp, orf_len);
935
936 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000937 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000938 stream_putc_at (s, capp, cap_len);
939}
940
941/* Fill in capability open option to the packet. */
942void
943bgp_open_capability (struct stream *s, struct peer *peer)
944{
945 u_char len;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700946 unsigned long cp, capp, rcapp;
paul718e3742002-12-13 20:15:29 +0000947 afi_t afi;
948 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000949 as_t local_as;
Vipin Kumardd49eb12014-09-30 14:36:38 -0700950 u_int32_t restart_time;
paul718e3742002-12-13 20:15:29 +0000951
952 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000953 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000954
955 /* Opt Parm Len. */
956 stream_putc (s, 0);
957
958 /* Do not send capability. */
959 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
960 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
961 return;
962
paul718e3742002-12-13 20:15:29 +0000963 /* IPv4 unicast. */
964 if (peer->afc[AFI_IP][SAFI_UNICAST])
965 {
966 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
967 stream_putc (s, BGP_OPEN_OPT_CAP);
968 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
969 stream_putc (s, CAPABILITY_CODE_MP);
970 stream_putc (s, CAPABILITY_CODE_MP_LEN);
971 stream_putw (s, AFI_IP);
972 stream_putc (s, 0);
973 stream_putc (s, SAFI_UNICAST);
974 }
975 /* IPv4 multicast. */
976 if (peer->afc[AFI_IP][SAFI_MULTICAST])
977 {
978 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
979 stream_putc (s, BGP_OPEN_OPT_CAP);
980 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
981 stream_putc (s, CAPABILITY_CODE_MP);
982 stream_putc (s, CAPABILITY_CODE_MP_LEN);
983 stream_putw (s, AFI_IP);
984 stream_putc (s, 0);
985 stream_putc (s, SAFI_MULTICAST);
986 }
987 /* IPv4 VPN */
988 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
989 {
990 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
991 stream_putc (s, BGP_OPEN_OPT_CAP);
992 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
993 stream_putc (s, CAPABILITY_CODE_MP);
994 stream_putc (s, CAPABILITY_CODE_MP_LEN);
995 stream_putw (s, AFI_IP);
996 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400997 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000998 }
Lou Berger298cc2f2016-01-12 13:42:02 -0500999 /* ENCAP */
1000 if (peer->afc[AFI_IP][SAFI_ENCAP])
1001 {
1002 peer->afc_adv[AFI_IP][SAFI_ENCAP] = 1;
1003 stream_putc (s, BGP_OPEN_OPT_CAP);
1004 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1005 stream_putc (s, CAPABILITY_CODE_MP);
1006 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1007 stream_putw (s, AFI_IP);
1008 stream_putc (s, 0);
1009 stream_putc (s, SAFI_ENCAP);
1010 }
paul718e3742002-12-13 20:15:29 +00001011 /* IPv6 unicast. */
1012 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1013 {
1014 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
1015 stream_putc (s, BGP_OPEN_OPT_CAP);
1016 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1017 stream_putc (s, CAPABILITY_CODE_MP);
1018 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1019 stream_putw (s, AFI_IP6);
1020 stream_putc (s, 0);
1021 stream_putc (s, SAFI_UNICAST);
1022 }
1023 /* IPv6 multicast. */
1024 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1025 {
1026 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
1027 stream_putc (s, BGP_OPEN_OPT_CAP);
1028 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1029 stream_putc (s, CAPABILITY_CODE_MP);
1030 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1031 stream_putw (s, AFI_IP6);
1032 stream_putc (s, 0);
1033 stream_putc (s, SAFI_MULTICAST);
1034 }
Lou Berger9da04bc2016-01-12 13:41:55 -05001035 /* IPv6 VPN. */
1036 if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
1037 {
1038 peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1;
1039 stream_putc (s, BGP_OPEN_OPT_CAP);
1040 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1041 stream_putc (s, CAPABILITY_CODE_MP);
1042 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1043 stream_putw (s, AFI_IP6);
1044 stream_putc (s, 0);
1045 stream_putc (s, SAFI_MPLS_LABELED_VPN);
1046 }
Lou Berger298cc2f2016-01-12 13:42:02 -05001047 /* IPv6 ENCAP. */
1048 if (peer->afc[AFI_IP6][SAFI_ENCAP])
1049 {
1050 peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 1;
1051 stream_putc (s, BGP_OPEN_OPT_CAP);
1052 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
1053 stream_putc (s, CAPABILITY_CODE_MP);
1054 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1055 stream_putw (s, AFI_IP6);
1056 stream_putc (s, 0);
1057 stream_putc (s, SAFI_ENCAP);
1058 }
paul718e3742002-12-13 20:15:29 +00001059
1060 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001061 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1062 stream_putc (s, BGP_OPEN_OPT_CAP);
1063 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1064 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1065 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1066 stream_putc (s, BGP_OPEN_OPT_CAP);
1067 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1068 stream_putc (s, CAPABILITY_CODE_REFRESH);
1069 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001070
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001071 /* AS4 */
1072 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1073 stream_putc (s, BGP_OPEN_OPT_CAP);
1074 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1075 stream_putc (s, CAPABILITY_CODE_AS4);
1076 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1077 if ( peer->change_local_as )
1078 local_as = peer->change_local_as;
1079 else
1080 local_as = peer->local_as;
1081 stream_putl (s, local_as );
1082
paul718e3742002-12-13 20:15:29 +00001083 /* ORF capability. */
1084 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1085 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1086 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1087 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1088 {
1089 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1090 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1091 }
1092
1093 /* Dynamic capability. */
1094 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1095 {
1096 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1097 stream_putc (s, BGP_OPEN_OPT_CAP);
1098 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1099 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1100 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1101 }
1102
Vipin Kumardd49eb12014-09-30 14:36:38 -07001103 /* Sending base graceful-restart capability irrespective of the config */
1104 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1105 stream_putc (s, BGP_OPEN_OPT_CAP);
1106 capp = stream_get_endp (s); /* Set Capability Len Pointer */
1107 stream_putc (s, 0); /* Capability Length */
1108 stream_putc (s, CAPABILITY_CODE_RESTART);
1109 rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
1110 stream_putc (s, 0);
1111 restart_time = peer->bgp->restart_time;
1112 if (peer->bgp->t_startup)
1113 {
1114 SET_FLAG (restart_time, RESTART_R_BIT);
1115 SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
1116 }
1117 stream_putw (s, restart_time);
1118
1119 /* Send address-family specific graceful-restart capability only when GR config
1120 is present */
hasso538621f2004-05-21 09:31:30 +00001121 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1122 {
Vipin Kumardd49eb12014-09-30 14:36:38 -07001123 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1124 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1125 if (peer->afc[afi][safi])
1126 {
1127 stream_putw (s, afi);
1128 stream_putc (s, safi);
1129 stream_putc (s, 0); //Forwarding is not retained as of now.
1130 }
1131 }
1132
1133 /* Total Graceful restart capability Len. */
1134 len = stream_get_endp (s) - rcapp - 1;
1135 stream_putc_at (s, rcapp, len);
1136
1137 /* Total Capability Len. */
1138 len = stream_get_endp (s) - capp - 1;
1139 stream_putc_at (s, capp, len);
hasso538621f2004-05-21 09:31:30 +00001140
paul718e3742002-12-13 20:15:29 +00001141 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001142 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001143 stream_putc_at (s, cp, len);
1144}