blob: d045dde542f63835b874e518d8a810e681b0d085 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP open message handling
2 Copyright (C) 1998, 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "linklist.h"
24#include "prefix.h"
25#include "stream.h"
26#include "thread.h"
27#include "log.h"
28#include "command.h"
Paul Jakma6d582722007-08-06 15:21:45 +000029#include "memory.h"
paul718e3742002-12-13 20:15:29 +000030
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_attr.h"
33#include "bgpd/bgp_debug.h"
34#include "bgpd/bgp_fsm.h"
35#include "bgpd/bgp_packet.h"
36#include "bgpd/bgp_open.h"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +000037#include "bgpd/bgp_aspath.h"
hasso538621f2004-05-21 09:31:30 +000038#include "bgpd/bgp_vty.h"
39
paul718e3742002-12-13 20:15:29 +000040/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
41 negotiate remote peer supports extentions or not. But if
42 remote-peer doesn't supports negotiation process itself. We would
43 like to do manual configuration.
44
45 So there is many configurable point. First of all we want set each
46 peer whether we send capability negotiation to the peer or not.
47 Next, if we send capability to the peer we want to set my capabilty
48 inforation at each peer. */
49
50void
51bgp_capability_vty_out (struct vty *vty, struct peer *peer)
52{
paul5228ad22004-06-04 17:58:18 +000053 char *pnt;
54 char *end;
Paul Jakma6d582722007-08-06 15:21:45 +000055 struct capability_mp_data mpc;
56 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +000057
58 pnt = peer->notify.data;
59 end = pnt + peer->notify.length;
Paul Jakma6d582722007-08-06 15:21:45 +000060
paul718e3742002-12-13 20:15:29 +000061 while (pnt < end)
62 {
Paul Jakma6d582722007-08-06 15:21:45 +000063 if (pnt + sizeof (struct capability_mp_data) + 2 > end)
paul718e3742002-12-13 20:15:29 +000064 return;
Paul Jakma6d582722007-08-06 15:21:45 +000065
66 hdr = (struct capability_header *)pnt;
67 if (pnt + hdr->length + 2 > end)
paul718e3742002-12-13 20:15:29 +000068 return;
69
Paul Jakma6d582722007-08-06 15:21:45 +000070 memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
71
72 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +000073 {
74 vty_out (vty, " Capability error for: Multi protocol ");
75
Paul Jakma6d582722007-08-06 15:21:45 +000076 switch (ntohs (mpc.afi))
paul718e3742002-12-13 20:15:29 +000077 {
78 case AFI_IP:
79 vty_out (vty, "AFI IPv4, ");
80 break;
81 case AFI_IP6:
82 vty_out (vty, "AFI IPv6, ");
83 break;
84 default:
Paul Jakma6d582722007-08-06 15:21:45 +000085 vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
paul718e3742002-12-13 20:15:29 +000086 break;
87 }
Paul Jakma6d582722007-08-06 15:21:45 +000088 switch (mpc.safi)
paul718e3742002-12-13 20:15:29 +000089 {
90 case SAFI_UNICAST:
91 vty_out (vty, "SAFI Unicast");
92 break;
93 case SAFI_MULTICAST:
94 vty_out (vty, "SAFI Multicast");
95 break;
Denis Ovsienko42e6d742011-07-14 12:36:19 +040096 case SAFI_MPLS_LABELED_VPN:
97 vty_out (vty, "SAFI MPLS-labeled VPN");
paul718e3742002-12-13 20:15:29 +000098 break;
99 default:
Paul Jakma6d582722007-08-06 15:21:45 +0000100 vty_out (vty, "SAFI Unknown %d ", mpc.safi);
paul718e3742002-12-13 20:15:29 +0000101 break;
102 }
103 vty_out (vty, "%s", VTY_NEWLINE);
104 }
Paul Jakma6d582722007-08-06 15:21:45 +0000105 else if (hdr->code >= 128)
paul718e3742002-12-13 20:15:29 +0000106 vty_out (vty, " Capability error: vendor specific capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000107 hdr->code);
paul718e3742002-12-13 20:15:29 +0000108 else
109 vty_out (vty, " Capability error: unknown capability code %d",
Paul Jakma6d582722007-08-06 15:21:45 +0000110 hdr->code);
paul718e3742002-12-13 20:15:29 +0000111
Paul Jakma6d582722007-08-06 15:21:45 +0000112 pnt += hdr->length + 2;
paul718e3742002-12-13 20:15:29 +0000113 }
114}
115
Paul Jakma6d582722007-08-06 15:21:45 +0000116static void
117bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
118{
119 mpc->afi = stream_getw (s);
120 mpc->reserved = stream_getc (s);
121 mpc->safi = stream_getc (s);
122}
123
124int
125bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
126{
Paul Jakma6d582722007-08-06 15:21:45 +0000127 switch (afi)
128 {
129 case AFI_IP:
130#ifdef HAVE_IPV6
131 case AFI_IP6:
132#endif
133 switch (*safi)
134 {
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400135 /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
136 case SAFI_MPLS_LABELED_VPN:
Paul Jakma6d582722007-08-06 15:21:45 +0000137 *safi = SAFI_MPLS_VPN;
138 case SAFI_UNICAST:
139 case SAFI_MULTICAST:
140 case SAFI_MPLS_VPN:
141 return 1;
142 }
143 }
144 zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
145
146 return 0;
147}
148
paul718e3742002-12-13 20:15:29 +0000149/* Set negotiated capability value. */
paul94f2b392005-06-28 12:44:16 +0000150static int
Paul Jakma6d582722007-08-06 15:21:45 +0000151bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
paul718e3742002-12-13 20:15:29 +0000152{
Paul Jakma6d582722007-08-06 15:21:45 +0000153 struct capability_mp_data mpc;
154 struct stream *s = BGP_INPUT (peer);
155
156 bgp_capability_mp_data (s, &mpc);
157
158 if (BGP_DEBUG (normal, NORMAL))
159 zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
160 peer->host, mpc.afi, mpc.safi);
161
162 if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
163 return -1;
164
165 /* Now safi remapped, and afi/safi are valid array indices */
166 peer->afc_recv[mpc.afi][mpc.safi] = 1;
167
168 if (peer->afc[mpc.afi][mpc.safi])
Paul Jakmae08286b2007-09-18 12:11:26 +0000169 peer->afc_nego[mpc.afi][mpc.safi] = 1;
Paul Jakma6d582722007-08-06 15:21:45 +0000170 else
171 return -1;
paul718e3742002-12-13 20:15:29 +0000172
173 return 0;
174}
175
paul94f2b392005-06-28 12:44:16 +0000176static void
paul718e3742002-12-13 20:15:29 +0000177bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
178 u_char type, u_char mode)
179{
180 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000181 zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
paul718e3742002-12-13 20:15:29 +0000182 peer->host, afi, safi, type, mode);
183}
184
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700185static const struct message orf_type_str[] =
paul718e3742002-12-13 20:15:29 +0000186{
Paul Jakma6d582722007-08-06 15:21:45 +0000187 { ORF_TYPE_PREFIX, "Prefixlist" },
188 { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
189};
Balaji.G837d16c2012-09-26 14:09:10 +0530190static const int orf_type_str_max = array_size(orf_type_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000191
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700192static const struct message orf_mode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000193{
194 { ORF_MODE_RECEIVE, "Receive" },
195 { ORF_MODE_SEND, "Send" },
196 { ORF_MODE_BOTH, "Both" },
197};
Balaji.G837d16c2012-09-26 14:09:10 +0530198static const int orf_mode_str_max = array_size(orf_mode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000199
200static int
201bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
202{
203 struct stream *s = BGP_INPUT (peer);
204 struct capability_orf_entry entry;
205 afi_t afi;
206 safi_t safi;
paul718e3742002-12-13 20:15:29 +0000207 u_char type;
208 u_char mode;
209 u_int16_t sm_cap = 0; /* capability send-mode receive */
210 u_int16_t rm_cap = 0; /* capability receive-mode receive */
211 int i;
212
Paul Jakma6d582722007-08-06 15:21:45 +0000213 /* ORF Entry header */
214 bgp_capability_mp_data (s, &entry.mpc);
215 entry.num = stream_getc (s);
216 afi = entry.mpc.afi;
217 safi = entry.mpc.safi;
218
paul718e3742002-12-13 20:15:29 +0000219 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma6d582722007-08-06 15:21:45 +0000220 zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
221 peer->host, entry.mpc.afi, entry.mpc.safi);
paul718e3742002-12-13 20:15:29 +0000222
223 /* Check AFI and SAFI. */
Paul Jakma6d582722007-08-06 15:21:45 +0000224 if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
paul718e3742002-12-13 20:15:29 +0000225 {
Paul Jakma6d582722007-08-06 15:21:45 +0000226 zlog_info ("%s Addr-family %d/%d not supported."
227 " Ignoring the ORF capability",
228 peer->host, entry.mpc.afi, entry.mpc.safi);
229 return 0;
230 }
231
232 /* validate number field */
233 if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
234 {
235 zlog_info ("%s ORF Capability entry length error,"
236 " Cap length %u, num %u",
237 peer->host, hdr->length, entry.num);
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
paul718e3742002-12-13 20:15:29 +0000239 return -1;
240 }
241
Paul Jakma6d582722007-08-06 15:21:45 +0000242 for (i = 0 ; i < entry.num ; i++)
paul718e3742002-12-13 20:15:29 +0000243 {
Paul Jakma6d582722007-08-06 15:21:45 +0000244 type = stream_getc(s);
245 mode = stream_getc(s);
246
paul718e3742002-12-13 20:15:29 +0000247 /* ORF Mode error check */
Paul Jakma6d582722007-08-06 15:21:45 +0000248 switch (mode)
249 {
250 case ORF_MODE_BOTH:
251 case ORF_MODE_SEND:
252 case ORF_MODE_RECEIVE:
253 break;
254 default:
255 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
256 continue;
paul718e3742002-12-13 20:15:29 +0000257 }
Paul Jakma6d582722007-08-06 15:21:45 +0000258 /* ORF Type and afi/safi error checks */
259 /* capcode versus type */
260 switch (hdr->code)
261 {
262 case CAPABILITY_CODE_ORF:
263 switch (type)
264 {
265 case ORF_TYPE_PREFIX:
266 break;
267 default:
268 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
269 continue;
270 }
271 break;
272 case CAPABILITY_CODE_ORF_OLD:
273 switch (type)
274 {
275 case ORF_TYPE_PREFIX_OLD:
276 break;
277 default:
278 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
279 continue;
280 }
281 break;
282 default:
283 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
284 continue;
285 }
286
287 /* AFI vs SAFI */
288 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
289 || (afi == AFI_IP && safi == SAFI_MULTICAST)
290 || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
291 {
292 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
293 continue;
294 }
295
296 if (BGP_DEBUG (normal, NORMAL))
297 zlog_debug ("%s OPEN has %s ORF capability"
298 " as %s for afi/safi: %d/%d",
299 peer->host, LOOKUP (orf_type_str, type),
300 LOOKUP (orf_mode_str, mode),
301 entry.mpc.afi, safi);
paul718e3742002-12-13 20:15:29 +0000302
Paul Jakma6d582722007-08-06 15:21:45 +0000303 if (hdr->code == CAPABILITY_CODE_ORF)
paul718e3742002-12-13 20:15:29 +0000304 {
Paul Jakma6d582722007-08-06 15:21:45 +0000305 sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
306 rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
paul718e3742002-12-13 20:15:29 +0000307 }
Paul Jakma6d582722007-08-06 15:21:45 +0000308 else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
paul718e3742002-12-13 20:15:29 +0000309 {
Paul Jakma6d582722007-08-06 15:21:45 +0000310 sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
311 rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
paul718e3742002-12-13 20:15:29 +0000312 }
313 else
314 {
315 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
316 continue;
317 }
318
319 switch (mode)
320 {
321 case ORF_MODE_BOTH:
322 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
323 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
324 break;
325 case ORF_MODE_SEND:
326 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
327 break;
328 case ORF_MODE_RECEIVE:
329 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
330 break;
331 }
332 }
333 return 0;
334}
335
paul94f2b392005-06-28 12:44:16 +0000336static int
Paul Jakma6d582722007-08-06 15:21:45 +0000337bgp_capability_orf (struct peer *peer, struct capability_header *hdr)
338{
339 struct stream *s = BGP_INPUT (peer);
340 size_t end = stream_get_getp (s) + hdr->length;
341
342 assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end);
343
344 /* We must have at least one ORF entry, as the caller has already done
345 * minimum length validation for the capability code - for ORF there must
346 * at least one ORF entry (header and unknown number of pairs of bytes).
347 */
348 do
349 {
350 if (bgp_capability_orf_entry (peer, hdr) == -1)
351 return -1;
352 }
353 while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end);
354
355 return 0;
356}
357
358static int
359bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
360{
361 struct stream *s = BGP_INPUT (peer);
362 u_int16_t restart_flag_time;
363 int restart_bit = 0;
364 size_t end = stream_get_getp (s) + caphdr->length;
365
366 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
367 restart_flag_time = stream_getw(s);
368 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
369 restart_bit = 1;
370 UNSET_FLAG (restart_flag_time, 0xF000);
371 peer->v_gr_restart = restart_flag_time;
372
373 if (BGP_DEBUG (normal, NORMAL))
374 {
375 zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
376 zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
377 peer->host, restart_bit ? " " : " not ",
378 peer->v_gr_restart);
379 }
380
Peter Pentchev21cc7692011-09-12 16:30:31 +0400381 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000382 {
383 afi_t afi = stream_getw (s);
384 safi_t safi = stream_getc (s);
385 u_char flag = stream_getc (s);
386
387 if (!bgp_afi_safi_valid_indices (afi, &safi))
388 {
389 if (BGP_DEBUG (normal, NORMAL))
390 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
391 " Ignore the Graceful Restart capability",
392 peer->host, afi, safi);
393 }
394 else if (!peer->afc[afi][safi])
395 {
396 if (BGP_DEBUG (normal, NORMAL))
397 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
398 " Ignore the Graceful Restart capability",
399 peer->host, afi, safi);
400 }
401 else
402 {
403 if (BGP_DEBUG (normal, NORMAL))
404 zlog_debug ("%s Address family %s is%spreserved", peer->host,
405 afi_safi_print (afi, safi),
406 CHECK_FLAG (peer->af_cap[afi][safi],
407 PEER_CAP_RESTART_AF_PRESERVE_RCV)
408 ? " " : " not ");
409
410 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
411 if (CHECK_FLAG (flag, RESTART_F_BIT))
412 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
413
414 }
415 }
416 return 0;
417}
418
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000419static as_t
420bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
421{
Paul Jakma58617392012-01-09 20:59:26 +0000422 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
423
424 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
425 {
426 zlog_err ("%s AS4 capability has incorrect data length %d",
427 peer->host, hdr->length);
428 return 0;
429 }
430
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000431 as_t as4 = stream_getl (BGP_INPUT(peer));
432
433 if (BGP_DEBUG (as4, AS4))
434 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
435 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000436 return as4;
437}
438
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700439static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000440{
Paul Jakma6d582722007-08-06 15:21:45 +0000441 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
442 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
443 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
444 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
445 { CAPABILITY_CODE_AS4, "4-octet AS number" },
446 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
447 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
448 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
449};
Balaji.G837d16c2012-09-26 14:09:10 +0530450static const int capcode_str_max = array_size(capcode_str);
Paul Jakma6d582722007-08-06 15:21:45 +0000451
452/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700453static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000454{
455 [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
456 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
457 [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
Paul Jakma370b64a2007-12-22 16:49:52 +0000458 [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
Paul Jakma6d582722007-08-06 15:21:45 +0000459 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
460 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
461 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
462 [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
463};
464
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800465/**
466 * Parse given capability.
Paul Jakma6d582722007-08-06 15:21:45 +0000467 * XXX: This is reading into a stream, but not using stream API
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800468 *
469 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
470 * capabilities were encountered.
Paul Jakma6d582722007-08-06 15:21:45 +0000471 */
472static int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800473bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
474 u_char **error)
paul718e3742002-12-13 20:15:29 +0000475{
476 int ret;
Paul Jakma6d582722007-08-06 15:21:45 +0000477 struct stream *s = BGP_INPUT (peer);
478 size_t end = stream_get_getp (s) + length;
479
480 assert (STREAM_READABLE (s) >= length);
481
482 while (stream_get_getp (s) < end)
paul718e3742002-12-13 20:15:29 +0000483 {
Paul Jakma6d582722007-08-06 15:21:45 +0000484 size_t start;
485 u_char *sp = stream_pnt (s);
486 struct capability_header caphdr;
487
paul718e3742002-12-13 20:15:29 +0000488 /* We need at least capability code and capability length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000489 if (stream_get_getp(s) + 2 > end)
paul718e3742002-12-13 20:15:29 +0000490 {
Paul Jakma6d582722007-08-06 15:21:45 +0000491 zlog_info ("%s Capability length error (< header)", peer->host);
paul718e3742002-12-13 20:15:29 +0000492 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
493 return -1;
494 }
Paul Jakma6d582722007-08-06 15:21:45 +0000495
496 caphdr.code = stream_getc (s);
497 caphdr.length = stream_getc (s);
498 start = stream_get_getp (s);
499
500 /* Capability length check sanity check. */
501 if (start + caphdr.length > end)
paul718e3742002-12-13 20:15:29 +0000502 {
Paul Jakma6d582722007-08-06 15:21:45 +0000503 zlog_info ("%s Capability length error (< length)", peer->host);
paul718e3742002-12-13 20:15:29 +0000504 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
505 return -1;
506 }
Paul Jakma6d582722007-08-06 15:21:45 +0000507
508 if (BGP_DEBUG (normal, NORMAL))
509 zlog_debug ("%s OPEN has %s capability (%u), length %u",
510 peer->host,
511 LOOKUP (capcode_str, caphdr.code),
512 caphdr.code, caphdr.length);
513
514 /* Length sanity check, type-specific, for known capabilities */
515 switch (caphdr.code)
516 {
517 case CAPABILITY_CODE_MP:
518 case CAPABILITY_CODE_REFRESH:
519 case CAPABILITY_CODE_REFRESH_OLD:
520 case CAPABILITY_CODE_ORF:
521 case CAPABILITY_CODE_ORF_OLD:
522 case CAPABILITY_CODE_RESTART:
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000523 case CAPABILITY_CODE_AS4:
Paul Jakma6d582722007-08-06 15:21:45 +0000524 case CAPABILITY_CODE_DYNAMIC:
525 /* Check length. */
526 if (caphdr.length < cap_minsizes[caphdr.code])
527 {
528 zlog_info ("%s %s Capability length error: got %u,"
529 " expected at least %u",
530 peer->host,
531 LOOKUP (capcode_str, caphdr.code),
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700532 caphdr.length,
533 (unsigned) cap_minsizes[caphdr.code]);
Paul Jakma6d582722007-08-06 15:21:45 +0000534 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
535 return -1;
536 }
537 /* we deliberately ignore unknown codes, see below */
538 default:
539 break;
540 }
541
542 switch (caphdr.code)
543 {
544 case CAPABILITY_CODE_MP:
545 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800546 *mp_capability = 1;
547
Paul Jakma6d582722007-08-06 15:21:45 +0000548 /* Ignore capability when override-capability is set. */
549 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
550 {
551 /* Set negotiated value. */
552 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000553
Paul Jakma6d582722007-08-06 15:21:45 +0000554 /* Unsupported Capability. */
555 if (ret < 0)
556 {
557 /* Store return data. */
558 memcpy (*error, sp, caphdr.length + 2);
559 *error += caphdr.length + 2;
560 }
561 }
562 }
563 break;
564 case CAPABILITY_CODE_REFRESH:
565 case CAPABILITY_CODE_REFRESH_OLD:
566 {
567 /* BGP refresh capability */
568 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
569 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
570 else
571 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
572 }
573 break;
574 case CAPABILITY_CODE_ORF:
575 case CAPABILITY_CODE_ORF_OLD:
576 if (bgp_capability_orf (peer, &caphdr))
577 return -1;
578 break;
579 case CAPABILITY_CODE_RESTART:
580 if (bgp_capability_restart (peer, &caphdr))
581 return -1;
582 break;
583 case CAPABILITY_CODE_DYNAMIC:
584 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
585 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000586 case CAPABILITY_CODE_AS4:
587 /* Already handled as a special-case parsing of the capabilities
588 * at the beginning of OPEN processing. So we care not a jot
589 * for the value really, only error case.
590 */
591 if (!bgp_capability_as4 (peer, &caphdr))
592 return -1;
593 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000594 default:
595 if (caphdr.code > 128)
596 {
597 /* We don't send Notification for unknown vendor specific
598 capabilities. It seems reasonable for now... */
599 zlog_warn ("%s Vendor specific capability %d",
600 peer->host, caphdr.code);
601 }
602 else
603 {
604 zlog_warn ("%s unrecognized capability code: %d - ignored",
605 peer->host, caphdr.code);
606 memcpy (*error, sp, caphdr.length + 2);
607 *error += caphdr.length + 2;
608 }
609 }
610 if (stream_get_getp(s) != (start + caphdr.length))
611 {
612 if (stream_get_getp(s) > (start + caphdr.length))
613 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
614 peer->host, LOOKUP (capcode_str, caphdr.code),
615 caphdr.length);
616 stream_set_getp (s, start + caphdr.length);
617 }
paul718e3742002-12-13 20:15:29 +0000618 }
619 return 0;
620}
621
paul94f2b392005-06-28 12:44:16 +0000622static int
Paul Jakma6d582722007-08-06 15:21:45 +0000623bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000624{
625 bgp_notify_send (peer,
626 BGP_NOTIFY_OPEN_ERR,
627 BGP_NOTIFY_OPEN_AUTH_FAILURE);
628 return -1;
629}
630
paul94f2b392005-06-28 12:44:16 +0000631static int
paul718e3742002-12-13 20:15:29 +0000632strict_capability_same (struct peer *peer)
633{
634 int i, j;
635
636 for (i = AFI_IP; i < AFI_MAX; i++)
637 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
638 if (peer->afc[i][j] != peer->afc_nego[i][j])
639 return 0;
640 return 1;
641}
642
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000643/* peek into option, stores ASN to *as4 if the AS4 capability was found.
644 * Returns 0 if no as4 found, as4cap value otherwise.
645 */
646as_t
647peek_for_as4_capability (struct peer *peer, u_char length)
648{
649 struct stream *s = BGP_INPUT (peer);
650 size_t orig_getp = stream_get_getp (s);
651 size_t end = orig_getp + length;
652 as_t as4 = 0;
653
654 /* The full capability parser will better flag the error.. */
655 if (STREAM_READABLE(s) < length)
656 return 0;
657
658 if (BGP_DEBUG (as4, AS4))
659 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
660 " peeking for as4",
661 peer->host, length);
662 /* the error cases we DONT handle, we ONLY try to read as4 out of
663 * correctly formatted options.
664 */
665 while (stream_get_getp(s) < end)
666 {
667 u_char opt_type;
668 u_char opt_length;
669
670 /* Check the length. */
671 if (stream_get_getp (s) + 2 > end)
672 goto end;
673
674 /* Fetch option type and length. */
675 opt_type = stream_getc (s);
676 opt_length = stream_getc (s);
677
678 /* Option length check. */
679 if (stream_get_getp (s) + opt_length > end)
680 goto end;
681
682 if (opt_type == BGP_OPEN_OPT_CAP)
683 {
684 unsigned long capd_start = stream_get_getp (s);
685 unsigned long capd_end = capd_start + opt_length;
686
687 assert (capd_end <= end);
688
689 while (stream_get_getp (s) < capd_end)
690 {
691 struct capability_header hdr;
692
693 if (stream_get_getp (s) + 2 > capd_end)
694 goto end;
695
696 hdr.code = stream_getc (s);
697 hdr.length = stream_getc (s);
698
699 if ((stream_get_getp(s) + hdr.length) > capd_end)
700 goto end;
701
702 if (hdr.code == CAPABILITY_CODE_AS4)
703 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000704 if (BGP_DEBUG (as4, AS4))
705 zlog_info ("[AS4] found AS4 capability, about to parse");
706 as4 = bgp_capability_as4 (peer, &hdr);
707
708 goto end;
709 }
710 stream_forward_getp (s, hdr.length);
711 }
712 }
713 }
714
715end:
716 stream_set_getp (s, orig_getp);
717 return as4;
718}
719
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800720/**
721 * Parse open option.
722 *
723 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
724 */
paul718e3742002-12-13 20:15:29 +0000725int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800726bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000727{
728 int ret;
paul718e3742002-12-13 20:15:29 +0000729 u_char *error;
730 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000731 struct stream *s = BGP_INPUT(peer);
732 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000733
734 ret = 0;
paul718e3742002-12-13 20:15:29 +0000735 error = error_data;
736
737 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000738 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000739 peer->host, length);
740
Paul Jakma6d582722007-08-06 15:21:45 +0000741 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000742 {
Paul Jakma6d582722007-08-06 15:21:45 +0000743 u_char opt_type;
744 u_char opt_length;
745
746 /* Must have at least an OPEN option header */
747 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000748 {
749 zlog_info ("%s Option length error", peer->host);
750 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
751 return -1;
752 }
753
754 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000755 opt_type = stream_getc (s);
756 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000757
758 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000759 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000760 {
761 zlog_info ("%s Option length error", peer->host);
762 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
763 return -1;
764 }
765
766 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000767 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000768 peer->host, opt_type,
769 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
770 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
771 opt_length);
772
773 switch (opt_type)
774 {
775 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000776 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000777 break;
778 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800779 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000780 break;
781 default:
782 bgp_notify_send (peer,
783 BGP_NOTIFY_OPEN_ERR,
784 BGP_NOTIFY_OPEN_UNSUP_PARAM);
785 ret = -1;
786 break;
787 }
788
789 /* Parse error. To accumulate all unsupported capability codes,
790 bgp_capability_parse does not return -1 when encounter
791 unsupported capability code. To detect that, please check
792 error and erro_data pointer, like below. */
793 if (ret < 0)
794 return -1;
paul718e3742002-12-13 20:15:29 +0000795 }
796
797 /* All OPEN option is parsed. Check capability when strict compare
798 flag is enabled.*/
799 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
800 {
801 /* If Unsupported Capability exists. */
802 if (error != error_data)
803 {
804 bgp_notify_send_with_data (peer,
805 BGP_NOTIFY_OPEN_ERR,
806 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
807 error_data, error - error_data);
808 return -1;
809 }
810
811 /* Check local capability does not negotiated with remote
812 peer. */
813 if (! strict_capability_same (peer))
814 {
815 bgp_notify_send (peer,
816 BGP_NOTIFY_OPEN_ERR,
817 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
818 return -1;
819 }
820 }
821
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800822 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000823 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800824 if (*mp_capability &&
825 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000826 {
827 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
828 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
829 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
830 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
831 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
832 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800833 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
834 "overlap with received MP capabilities",
835 peer->host);
paul718e3742002-12-13 20:15:29 +0000836
837 if (error != error_data)
838
839 bgp_notify_send_with_data (peer,
840 BGP_NOTIFY_OPEN_ERR,
841 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
842 error_data, error - error_data);
843 else
844 bgp_notify_send (peer,
845 BGP_NOTIFY_OPEN_ERR,
846 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
847 return -1;
848 }
849 }
850 return 0;
851}
852
paul94f2b392005-06-28 12:44:16 +0000853static void
paul718e3742002-12-13 20:15:29 +0000854bgp_open_capability_orf (struct stream *s, struct peer *peer,
855 afi_t afi, safi_t safi, u_char code)
856{
857 u_char cap_len;
858 u_char orf_len;
859 unsigned long capp;
860 unsigned long orfp;
861 unsigned long numberp;
862 int number_of_orfs = 0;
863
864 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400865 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000866
867 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000868 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000869 stream_putc (s, 0); /* Capability Length */
870 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000871 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000872 stream_putc (s, 0); /* ORF Length */
873 stream_putw (s, afi);
874 stream_putc (s, 0);
875 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000876 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000877 stream_putc (s, 0); /* Number of ORFs */
878
879 /* Address Prefix ORF */
880 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
881 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
882 {
883 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
884 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
885
886 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
887 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
888 {
889 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
890 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
891 stream_putc (s, ORF_MODE_BOTH);
892 }
893 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
894 {
895 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
896 stream_putc (s, ORF_MODE_SEND);
897 }
898 else
899 {
900 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
901 stream_putc (s, ORF_MODE_RECEIVE);
902 }
903 number_of_orfs++;
904 }
905
906 /* Total Number of ORFs. */
907 stream_putc_at (s, numberp, number_of_orfs);
908
909 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000910 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000911 stream_putc_at (s, orfp, orf_len);
912
913 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000914 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000915 stream_putc_at (s, capp, cap_len);
916}
917
918/* Fill in capability open option to the packet. */
919void
920bgp_open_capability (struct stream *s, struct peer *peer)
921{
922 u_char len;
923 unsigned long cp;
924 afi_t afi;
925 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000926 as_t local_as;
paul718e3742002-12-13 20:15:29 +0000927
928 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000929 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000930
931 /* Opt Parm Len. */
932 stream_putc (s, 0);
933
934 /* Do not send capability. */
935 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
936 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
937 return;
938
paul718e3742002-12-13 20:15:29 +0000939 /* IPv4 unicast. */
940 if (peer->afc[AFI_IP][SAFI_UNICAST])
941 {
942 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
943 stream_putc (s, BGP_OPEN_OPT_CAP);
944 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
945 stream_putc (s, CAPABILITY_CODE_MP);
946 stream_putc (s, CAPABILITY_CODE_MP_LEN);
947 stream_putw (s, AFI_IP);
948 stream_putc (s, 0);
949 stream_putc (s, SAFI_UNICAST);
950 }
951 /* IPv4 multicast. */
952 if (peer->afc[AFI_IP][SAFI_MULTICAST])
953 {
954 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
955 stream_putc (s, BGP_OPEN_OPT_CAP);
956 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
957 stream_putc (s, CAPABILITY_CODE_MP);
958 stream_putc (s, CAPABILITY_CODE_MP_LEN);
959 stream_putw (s, AFI_IP);
960 stream_putc (s, 0);
961 stream_putc (s, SAFI_MULTICAST);
962 }
963 /* IPv4 VPN */
964 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
965 {
966 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 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);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400973 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000974 }
975#ifdef HAVE_IPV6
976 /* IPv6 unicast. */
977 if (peer->afc[AFI_IP6][SAFI_UNICAST])
978 {
979 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
980 stream_putc (s, BGP_OPEN_OPT_CAP);
981 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
982 stream_putc (s, CAPABILITY_CODE_MP);
983 stream_putc (s, CAPABILITY_CODE_MP_LEN);
984 stream_putw (s, AFI_IP6);
985 stream_putc (s, 0);
986 stream_putc (s, SAFI_UNICAST);
987 }
988 /* IPv6 multicast. */
989 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
990 {
991 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
992 stream_putc (s, BGP_OPEN_OPT_CAP);
993 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
994 stream_putc (s, CAPABILITY_CODE_MP);
995 stream_putc (s, CAPABILITY_CODE_MP_LEN);
996 stream_putw (s, AFI_IP6);
997 stream_putc (s, 0);
998 stream_putc (s, SAFI_MULTICAST);
999 }
1000#endif /* HAVE_IPV6 */
1001
1002 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001003 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1004 stream_putc (s, BGP_OPEN_OPT_CAP);
1005 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1006 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1007 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1008 stream_putc (s, BGP_OPEN_OPT_CAP);
1009 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1010 stream_putc (s, CAPABILITY_CODE_REFRESH);
1011 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001012
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001013 /* AS4 */
1014 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1015 stream_putc (s, BGP_OPEN_OPT_CAP);
1016 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1017 stream_putc (s, CAPABILITY_CODE_AS4);
1018 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1019 if ( peer->change_local_as )
1020 local_as = peer->change_local_as;
1021 else
1022 local_as = peer->local_as;
1023 stream_putl (s, local_as );
1024
paul718e3742002-12-13 20:15:29 +00001025 /* ORF capability. */
1026 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1027 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1028 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1029 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1030 {
1031 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1032 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1033 }
1034
1035 /* Dynamic capability. */
1036 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1037 {
1038 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1039 stream_putc (s, BGP_OPEN_OPT_CAP);
1040 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1041 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1042 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1043 }
1044
hasso538621f2004-05-21 09:31:30 +00001045 /* Graceful restart capability */
1046 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1047 {
1048 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1049 stream_putc (s, BGP_OPEN_OPT_CAP);
1050 stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
1051 stream_putc (s, CAPABILITY_CODE_RESTART);
1052 stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
1053 stream_putw (s, peer->bgp->restart_time);
1054 }
1055
paul718e3742002-12-13 20:15:29 +00001056 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001057 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001058 stream_putc_at (s, cp, len);
1059}