blob: 0326d01bc72a8bbdc474f2af128edeeddb802b82 [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};
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700190static const int orf_type_str_max
191 = sizeof(orf_type_str)/sizeof(orf_type_str[0]);
Paul Jakma6d582722007-08-06 15:21:45 +0000192
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700193static const struct message orf_mode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000194{
195 { ORF_MODE_RECEIVE, "Receive" },
196 { ORF_MODE_SEND, "Send" },
197 { ORF_MODE_BOTH, "Both" },
198};
Stephen Hemminger8f5abac2009-05-15 10:16:34 -0700199static const int orf_mode_str_max
200 = sizeof(orf_mode_str)/sizeof(orf_mode_str[0]);
Paul Jakma6d582722007-08-06 15:21:45 +0000201
202static int
203bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
204{
205 struct stream *s = BGP_INPUT (peer);
206 struct capability_orf_entry entry;
207 afi_t afi;
208 safi_t safi;
paul718e3742002-12-13 20:15:29 +0000209 u_char type;
210 u_char mode;
211 u_int16_t sm_cap = 0; /* capability send-mode receive */
212 u_int16_t rm_cap = 0; /* capability receive-mode receive */
213 int i;
214
Paul Jakma6d582722007-08-06 15:21:45 +0000215 /* ORF Entry header */
216 bgp_capability_mp_data (s, &entry.mpc);
217 entry.num = stream_getc (s);
218 afi = entry.mpc.afi;
219 safi = entry.mpc.safi;
220
paul718e3742002-12-13 20:15:29 +0000221 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma6d582722007-08-06 15:21:45 +0000222 zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
223 peer->host, entry.mpc.afi, entry.mpc.safi);
paul718e3742002-12-13 20:15:29 +0000224
225 /* Check AFI and SAFI. */
Paul Jakma6d582722007-08-06 15:21:45 +0000226 if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
paul718e3742002-12-13 20:15:29 +0000227 {
Paul Jakma6d582722007-08-06 15:21:45 +0000228 zlog_info ("%s Addr-family %d/%d not supported."
229 " Ignoring the ORF capability",
230 peer->host, entry.mpc.afi, entry.mpc.safi);
231 return 0;
232 }
233
234 /* validate number field */
235 if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
236 {
237 zlog_info ("%s ORF Capability entry length error,"
238 " Cap length %u, num %u",
239 peer->host, hdr->length, entry.num);
240 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
paul718e3742002-12-13 20:15:29 +0000241 return -1;
242 }
243
Paul Jakma6d582722007-08-06 15:21:45 +0000244 for (i = 0 ; i < entry.num ; i++)
paul718e3742002-12-13 20:15:29 +0000245 {
Paul Jakma6d582722007-08-06 15:21:45 +0000246 type = stream_getc(s);
247 mode = stream_getc(s);
248
paul718e3742002-12-13 20:15:29 +0000249 /* ORF Mode error check */
Paul Jakma6d582722007-08-06 15:21:45 +0000250 switch (mode)
251 {
252 case ORF_MODE_BOTH:
253 case ORF_MODE_SEND:
254 case ORF_MODE_RECEIVE:
255 break;
256 default:
257 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
258 continue;
paul718e3742002-12-13 20:15:29 +0000259 }
Paul Jakma6d582722007-08-06 15:21:45 +0000260 /* ORF Type and afi/safi error checks */
261 /* capcode versus type */
262 switch (hdr->code)
263 {
264 case CAPABILITY_CODE_ORF:
265 switch (type)
266 {
267 case ORF_TYPE_PREFIX:
268 break;
269 default:
270 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
271 continue;
272 }
273 break;
274 case CAPABILITY_CODE_ORF_OLD:
275 switch (type)
276 {
277 case ORF_TYPE_PREFIX_OLD:
278 break;
279 default:
280 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
281 continue;
282 }
283 break;
284 default:
285 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
286 continue;
287 }
288
289 /* AFI vs SAFI */
290 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
291 || (afi == AFI_IP && safi == SAFI_MULTICAST)
292 || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
293 {
294 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
295 continue;
296 }
297
298 if (BGP_DEBUG (normal, NORMAL))
299 zlog_debug ("%s OPEN has %s ORF capability"
300 " as %s for afi/safi: %d/%d",
301 peer->host, LOOKUP (orf_type_str, type),
302 LOOKUP (orf_mode_str, mode),
303 entry.mpc.afi, safi);
paul718e3742002-12-13 20:15:29 +0000304
Paul Jakma6d582722007-08-06 15:21:45 +0000305 if (hdr->code == CAPABILITY_CODE_ORF)
paul718e3742002-12-13 20:15:29 +0000306 {
Paul Jakma6d582722007-08-06 15:21:45 +0000307 sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
308 rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
paul718e3742002-12-13 20:15:29 +0000309 }
Paul Jakma6d582722007-08-06 15:21:45 +0000310 else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
paul718e3742002-12-13 20:15:29 +0000311 {
Paul Jakma6d582722007-08-06 15:21:45 +0000312 sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
313 rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
paul718e3742002-12-13 20:15:29 +0000314 }
315 else
316 {
317 bgp_capability_orf_not_support (peer, afi, safi, type, mode);
318 continue;
319 }
320
321 switch (mode)
322 {
323 case ORF_MODE_BOTH:
324 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
325 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
326 break;
327 case ORF_MODE_SEND:
328 SET_FLAG (peer->af_cap[afi][safi], sm_cap);
329 break;
330 case ORF_MODE_RECEIVE:
331 SET_FLAG (peer->af_cap[afi][safi], rm_cap);
332 break;
333 }
334 }
335 return 0;
336}
337
paul94f2b392005-06-28 12:44:16 +0000338static int
Paul Jakma6d582722007-08-06 15:21:45 +0000339bgp_capability_orf (struct peer *peer, struct capability_header *hdr)
340{
341 struct stream *s = BGP_INPUT (peer);
342 size_t end = stream_get_getp (s) + hdr->length;
343
344 assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end);
345
346 /* We must have at least one ORF entry, as the caller has already done
347 * minimum length validation for the capability code - for ORF there must
348 * at least one ORF entry (header and unknown number of pairs of bytes).
349 */
350 do
351 {
352 if (bgp_capability_orf_entry (peer, hdr) == -1)
353 return -1;
354 }
355 while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end);
356
357 return 0;
358}
359
360static int
361bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
362{
363 struct stream *s = BGP_INPUT (peer);
364 u_int16_t restart_flag_time;
365 int restart_bit = 0;
366 size_t end = stream_get_getp (s) + caphdr->length;
367
368 SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
369 restart_flag_time = stream_getw(s);
370 if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
371 restart_bit = 1;
372 UNSET_FLAG (restart_flag_time, 0xF000);
373 peer->v_gr_restart = restart_flag_time;
374
375 if (BGP_DEBUG (normal, NORMAL))
376 {
377 zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
378 zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
379 peer->host, restart_bit ? " " : " not ",
380 peer->v_gr_restart);
381 }
382
Peter Pentchev21cc7692011-09-12 16:30:31 +0400383 while (stream_get_getp (s) + 4 <= end)
Paul Jakma6d582722007-08-06 15:21:45 +0000384 {
385 afi_t afi = stream_getw (s);
386 safi_t safi = stream_getc (s);
387 u_char flag = stream_getc (s);
388
389 if (!bgp_afi_safi_valid_indices (afi, &safi))
390 {
391 if (BGP_DEBUG (normal, NORMAL))
392 zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
393 " Ignore the Graceful Restart capability",
394 peer->host, afi, safi);
395 }
396 else if (!peer->afc[afi][safi])
397 {
398 if (BGP_DEBUG (normal, NORMAL))
399 zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
400 " Ignore the Graceful Restart capability",
401 peer->host, afi, safi);
402 }
403 else
404 {
405 if (BGP_DEBUG (normal, NORMAL))
406 zlog_debug ("%s Address family %s is%spreserved", peer->host,
407 afi_safi_print (afi, safi),
408 CHECK_FLAG (peer->af_cap[afi][safi],
409 PEER_CAP_RESTART_AF_PRESERVE_RCV)
410 ? " " : " not ");
411
412 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
413 if (CHECK_FLAG (flag, RESTART_F_BIT))
414 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
415
416 }
417 }
418 return 0;
419}
420
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000421static as_t
422bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
423{
Paul Jakma58617392012-01-09 20:59:26 +0000424 SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
425
426 if (hdr->length != CAPABILITY_CODE_AS4_LEN)
427 {
428 zlog_err ("%s AS4 capability has incorrect data length %d",
429 peer->host, hdr->length);
430 return 0;
431 }
432
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000433 as_t as4 = stream_getl (BGP_INPUT(peer));
434
435 if (BGP_DEBUG (as4, AS4))
436 zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
437 peer->host, as4);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000438 return as4;
439}
440
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700441static const struct message capcode_str[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000442{
Paul Jakma6d582722007-08-06 15:21:45 +0000443 { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
444 { CAPABILITY_CODE_REFRESH, "Route Refresh" },
445 { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
446 { CAPABILITY_CODE_RESTART, "Graceful Restart" },
447 { CAPABILITY_CODE_AS4, "4-octet AS number" },
448 { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
449 { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
450 { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
451};
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700452static const int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]);
Paul Jakma6d582722007-08-06 15:21:45 +0000453
454/* Minimum sizes for length field of each cap (so not inc. the header) */
Stephen Hemmingerfc52f952009-05-15 09:48:55 -0700455static const size_t cap_minsizes[] =
Paul Jakma6d582722007-08-06 15:21:45 +0000456{
457 [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
458 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
459 [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
Paul Jakma370b64a2007-12-22 16:49:52 +0000460 [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
Paul Jakma6d582722007-08-06 15:21:45 +0000461 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
462 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
463 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
464 [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
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);
paul718e3742002-12-13 20:15:29 +0000494 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
495 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);
paul718e3742002-12-13 20:15:29 +0000506 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
507 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 Jakma6d582722007-08-06 15:21:45 +0000536 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
537 return -1;
538 }
539 /* we deliberately ignore unknown codes, see below */
540 default:
541 break;
542 }
543
544 switch (caphdr.code)
545 {
546 case CAPABILITY_CODE_MP:
547 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800548 *mp_capability = 1;
549
Paul Jakma6d582722007-08-06 15:21:45 +0000550 /* Ignore capability when override-capability is set. */
551 if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
552 {
553 /* Set negotiated value. */
554 ret = bgp_capability_mp (peer, &caphdr);
paul718e3742002-12-13 20:15:29 +0000555
Paul Jakma6d582722007-08-06 15:21:45 +0000556 /* Unsupported Capability. */
557 if (ret < 0)
558 {
559 /* Store return data. */
560 memcpy (*error, sp, caphdr.length + 2);
561 *error += caphdr.length + 2;
562 }
563 }
564 }
565 break;
566 case CAPABILITY_CODE_REFRESH:
567 case CAPABILITY_CODE_REFRESH_OLD:
568 {
569 /* BGP refresh capability */
570 if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
571 SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
572 else
573 SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
574 }
575 break;
576 case CAPABILITY_CODE_ORF:
577 case CAPABILITY_CODE_ORF_OLD:
578 if (bgp_capability_orf (peer, &caphdr))
579 return -1;
580 break;
581 case CAPABILITY_CODE_RESTART:
582 if (bgp_capability_restart (peer, &caphdr))
583 return -1;
584 break;
585 case CAPABILITY_CODE_DYNAMIC:
586 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
587 break;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000588 case CAPABILITY_CODE_AS4:
589 /* Already handled as a special-case parsing of the capabilities
590 * at the beginning of OPEN processing. So we care not a jot
591 * for the value really, only error case.
592 */
593 if (!bgp_capability_as4 (peer, &caphdr))
594 return -1;
595 break;
Paul Jakma6d582722007-08-06 15:21:45 +0000596 default:
597 if (caphdr.code > 128)
598 {
599 /* We don't send Notification for unknown vendor specific
600 capabilities. It seems reasonable for now... */
601 zlog_warn ("%s Vendor specific capability %d",
602 peer->host, caphdr.code);
603 }
604 else
605 {
606 zlog_warn ("%s unrecognized capability code: %d - ignored",
607 peer->host, caphdr.code);
608 memcpy (*error, sp, caphdr.length + 2);
609 *error += caphdr.length + 2;
610 }
611 }
612 if (stream_get_getp(s) != (start + caphdr.length))
613 {
614 if (stream_get_getp(s) > (start + caphdr.length))
615 zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
616 peer->host, LOOKUP (capcode_str, caphdr.code),
617 caphdr.length);
618 stream_set_getp (s, start + caphdr.length);
619 }
paul718e3742002-12-13 20:15:29 +0000620 }
621 return 0;
622}
623
paul94f2b392005-06-28 12:44:16 +0000624static int
Paul Jakma6d582722007-08-06 15:21:45 +0000625bgp_auth_parse (struct peer *peer, size_t length)
paul718e3742002-12-13 20:15:29 +0000626{
627 bgp_notify_send (peer,
628 BGP_NOTIFY_OPEN_ERR,
629 BGP_NOTIFY_OPEN_AUTH_FAILURE);
630 return -1;
631}
632
paul94f2b392005-06-28 12:44:16 +0000633static int
paul718e3742002-12-13 20:15:29 +0000634strict_capability_same (struct peer *peer)
635{
636 int i, j;
637
638 for (i = AFI_IP; i < AFI_MAX; i++)
639 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
640 if (peer->afc[i][j] != peer->afc_nego[i][j])
641 return 0;
642 return 1;
643}
644
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000645/* peek into option, stores ASN to *as4 if the AS4 capability was found.
646 * Returns 0 if no as4 found, as4cap value otherwise.
647 */
648as_t
649peek_for_as4_capability (struct peer *peer, u_char length)
650{
651 struct stream *s = BGP_INPUT (peer);
652 size_t orig_getp = stream_get_getp (s);
653 size_t end = orig_getp + length;
654 as_t as4 = 0;
655
656 /* The full capability parser will better flag the error.. */
657 if (STREAM_READABLE(s) < length)
658 return 0;
659
660 if (BGP_DEBUG (as4, AS4))
661 zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
662 " peeking for as4",
663 peer->host, length);
664 /* the error cases we DONT handle, we ONLY try to read as4 out of
665 * correctly formatted options.
666 */
667 while (stream_get_getp(s) < end)
668 {
669 u_char opt_type;
670 u_char opt_length;
671
672 /* Check the length. */
673 if (stream_get_getp (s) + 2 > end)
674 goto end;
675
676 /* Fetch option type and length. */
677 opt_type = stream_getc (s);
678 opt_length = stream_getc (s);
679
680 /* Option length check. */
681 if (stream_get_getp (s) + opt_length > end)
682 goto end;
683
684 if (opt_type == BGP_OPEN_OPT_CAP)
685 {
686 unsigned long capd_start = stream_get_getp (s);
687 unsigned long capd_end = capd_start + opt_length;
688
689 assert (capd_end <= end);
690
691 while (stream_get_getp (s) < capd_end)
692 {
693 struct capability_header hdr;
694
695 if (stream_get_getp (s) + 2 > capd_end)
696 goto end;
697
698 hdr.code = stream_getc (s);
699 hdr.length = stream_getc (s);
700
701 if ((stream_get_getp(s) + hdr.length) > capd_end)
702 goto end;
703
704 if (hdr.code == CAPABILITY_CODE_AS4)
705 {
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000706 if (BGP_DEBUG (as4, AS4))
707 zlog_info ("[AS4] found AS4 capability, about to parse");
708 as4 = bgp_capability_as4 (peer, &hdr);
709
710 goto end;
711 }
712 stream_forward_getp (s, hdr.length);
713 }
714 }
715 }
716
717end:
718 stream_set_getp (s, orig_getp);
719 return as4;
720}
721
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800722/**
723 * Parse open option.
724 *
725 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
726 */
paul718e3742002-12-13 20:15:29 +0000727int
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800728bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
paul718e3742002-12-13 20:15:29 +0000729{
730 int ret;
paul718e3742002-12-13 20:15:29 +0000731 u_char *error;
732 u_char error_data[BGP_MAX_PACKET_SIZE];
Paul Jakma6d582722007-08-06 15:21:45 +0000733 struct stream *s = BGP_INPUT(peer);
734 size_t end = stream_get_getp (s) + length;
paul718e3742002-12-13 20:15:29 +0000735
736 ret = 0;
paul718e3742002-12-13 20:15:29 +0000737 error = error_data;
738
739 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000740 zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
paul718e3742002-12-13 20:15:29 +0000741 peer->host, length);
742
Paul Jakma6d582722007-08-06 15:21:45 +0000743 while (stream_get_getp(s) < end)
paul718e3742002-12-13 20:15:29 +0000744 {
Paul Jakma6d582722007-08-06 15:21:45 +0000745 u_char opt_type;
746 u_char opt_length;
747
748 /* Must have at least an OPEN option header */
749 if (STREAM_READABLE(s) < 2)
paul718e3742002-12-13 20:15:29 +0000750 {
751 zlog_info ("%s Option length error", peer->host);
752 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
753 return -1;
754 }
755
756 /* Fetch option type and length. */
Paul Jakma6d582722007-08-06 15:21:45 +0000757 opt_type = stream_getc (s);
758 opt_length = stream_getc (s);
paul718e3742002-12-13 20:15:29 +0000759
760 /* Option length check. */
Paul Jakma6d582722007-08-06 15:21:45 +0000761 if (STREAM_READABLE (s) < opt_length)
paul718e3742002-12-13 20:15:29 +0000762 {
763 zlog_info ("%s Option length error", peer->host);
764 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
765 return -1;
766 }
767
768 if (BGP_DEBUG (normal, NORMAL))
ajs8325cd72004-12-08 20:47:40 +0000769 zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
paul718e3742002-12-13 20:15:29 +0000770 peer->host, opt_type,
771 opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
772 opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
773 opt_length);
774
775 switch (opt_type)
776 {
777 case BGP_OPEN_OPT_AUTH:
Paul Jakma6d582722007-08-06 15:21:45 +0000778 ret = bgp_auth_parse (peer, opt_length);
paul718e3742002-12-13 20:15:29 +0000779 break;
780 case BGP_OPEN_OPT_CAP:
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800781 ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
paul718e3742002-12-13 20:15:29 +0000782 break;
783 default:
784 bgp_notify_send (peer,
785 BGP_NOTIFY_OPEN_ERR,
786 BGP_NOTIFY_OPEN_UNSUP_PARAM);
787 ret = -1;
788 break;
789 }
790
791 /* Parse error. To accumulate all unsupported capability codes,
792 bgp_capability_parse does not return -1 when encounter
793 unsupported capability code. To detect that, please check
794 error and erro_data pointer, like below. */
795 if (ret < 0)
796 return -1;
paul718e3742002-12-13 20:15:29 +0000797 }
798
799 /* All OPEN option is parsed. Check capability when strict compare
800 flag is enabled.*/
801 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
802 {
803 /* If Unsupported Capability exists. */
804 if (error != error_data)
805 {
806 bgp_notify_send_with_data (peer,
807 BGP_NOTIFY_OPEN_ERR,
808 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
809 error_data, error - error_data);
810 return -1;
811 }
812
813 /* Check local capability does not negotiated with remote
814 peer. */
815 if (! strict_capability_same (peer))
816 {
817 bgp_notify_send (peer,
818 BGP_NOTIFY_OPEN_ERR,
819 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
820 return -1;
821 }
822 }
823
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800824 /* Check there are no common AFI/SAFIs and send Unsupported Capability
paul718e3742002-12-13 20:15:29 +0000825 error. */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800826 if (*mp_capability &&
827 ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +0000828 {
829 if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
830 && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
831 && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
832 && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
833 && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
834 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -0800835 plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
836 "overlap with received MP capabilities",
837 peer->host);
paul718e3742002-12-13 20:15:29 +0000838
839 if (error != error_data)
840
841 bgp_notify_send_with_data (peer,
842 BGP_NOTIFY_OPEN_ERR,
843 BGP_NOTIFY_OPEN_UNSUP_CAPBL,
844 error_data, error - error_data);
845 else
846 bgp_notify_send (peer,
847 BGP_NOTIFY_OPEN_ERR,
848 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
849 return -1;
850 }
851 }
852 return 0;
853}
854
paul94f2b392005-06-28 12:44:16 +0000855static void
paul718e3742002-12-13 20:15:29 +0000856bgp_open_capability_orf (struct stream *s, struct peer *peer,
857 afi_t afi, safi_t safi, u_char code)
858{
859 u_char cap_len;
860 u_char orf_len;
861 unsigned long capp;
862 unsigned long orfp;
863 unsigned long numberp;
864 int number_of_orfs = 0;
865
866 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400867 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000868
869 stream_putc (s, BGP_OPEN_OPT_CAP);
paul9985f832005-02-09 15:51:56 +0000870 capp = stream_get_endp (s); /* Set Capability Len Pointer */
paul718e3742002-12-13 20:15:29 +0000871 stream_putc (s, 0); /* Capability Length */
872 stream_putc (s, code); /* Capability Code */
paul9985f832005-02-09 15:51:56 +0000873 orfp = stream_get_endp (s); /* Set ORF Len Pointer */
paul718e3742002-12-13 20:15:29 +0000874 stream_putc (s, 0); /* ORF Length */
875 stream_putw (s, afi);
876 stream_putc (s, 0);
877 stream_putc (s, safi);
paul9985f832005-02-09 15:51:56 +0000878 numberp = stream_get_endp (s); /* Set Number Pointer */
paul718e3742002-12-13 20:15:29 +0000879 stream_putc (s, 0); /* Number of ORFs */
880
881 /* Address Prefix ORF */
882 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
883 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
884 {
885 stream_putc (s, (code == CAPABILITY_CODE_ORF ?
886 ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
887
888 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
889 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
890 {
891 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
892 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
893 stream_putc (s, ORF_MODE_BOTH);
894 }
895 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
896 {
897 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
898 stream_putc (s, ORF_MODE_SEND);
899 }
900 else
901 {
902 SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
903 stream_putc (s, ORF_MODE_RECEIVE);
904 }
905 number_of_orfs++;
906 }
907
908 /* Total Number of ORFs. */
909 stream_putc_at (s, numberp, number_of_orfs);
910
911 /* Total ORF Len. */
paul9985f832005-02-09 15:51:56 +0000912 orf_len = stream_get_endp (s) - orfp - 1;
paul718e3742002-12-13 20:15:29 +0000913 stream_putc_at (s, orfp, orf_len);
914
915 /* Total Capability Len. */
paul9985f832005-02-09 15:51:56 +0000916 cap_len = stream_get_endp (s) - capp - 1;
paul718e3742002-12-13 20:15:29 +0000917 stream_putc_at (s, capp, cap_len);
918}
919
920/* Fill in capability open option to the packet. */
921void
922bgp_open_capability (struct stream *s, struct peer *peer)
923{
924 u_char len;
925 unsigned long cp;
926 afi_t afi;
927 safi_t safi;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000928 as_t local_as;
paul718e3742002-12-13 20:15:29 +0000929
930 /* Remember current pointer for Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +0000931 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000932
933 /* Opt Parm Len. */
934 stream_putc (s, 0);
935
936 /* Do not send capability. */
937 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
938 || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
939 return;
940
paul718e3742002-12-13 20:15:29 +0000941 /* IPv4 unicast. */
942 if (peer->afc[AFI_IP][SAFI_UNICAST])
943 {
944 peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
945 stream_putc (s, BGP_OPEN_OPT_CAP);
946 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
947 stream_putc (s, CAPABILITY_CODE_MP);
948 stream_putc (s, CAPABILITY_CODE_MP_LEN);
949 stream_putw (s, AFI_IP);
950 stream_putc (s, 0);
951 stream_putc (s, SAFI_UNICAST);
952 }
953 /* IPv4 multicast. */
954 if (peer->afc[AFI_IP][SAFI_MULTICAST])
955 {
956 peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
957 stream_putc (s, BGP_OPEN_OPT_CAP);
958 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
959 stream_putc (s, CAPABILITY_CODE_MP);
960 stream_putc (s, CAPABILITY_CODE_MP_LEN);
961 stream_putw (s, AFI_IP);
962 stream_putc (s, 0);
963 stream_putc (s, SAFI_MULTICAST);
964 }
965 /* IPv4 VPN */
966 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
967 {
968 peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
969 stream_putc (s, BGP_OPEN_OPT_CAP);
970 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
971 stream_putc (s, CAPABILITY_CODE_MP);
972 stream_putc (s, CAPABILITY_CODE_MP_LEN);
973 stream_putw (s, AFI_IP);
974 stream_putc (s, 0);
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400975 stream_putc (s, SAFI_MPLS_LABELED_VPN);
paul718e3742002-12-13 20:15:29 +0000976 }
977#ifdef HAVE_IPV6
978 /* IPv6 unicast. */
979 if (peer->afc[AFI_IP6][SAFI_UNICAST])
980 {
981 peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
982 stream_putc (s, BGP_OPEN_OPT_CAP);
983 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
984 stream_putc (s, CAPABILITY_CODE_MP);
985 stream_putc (s, CAPABILITY_CODE_MP_LEN);
986 stream_putw (s, AFI_IP6);
987 stream_putc (s, 0);
988 stream_putc (s, SAFI_UNICAST);
989 }
990 /* IPv6 multicast. */
991 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
992 {
993 peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
994 stream_putc (s, BGP_OPEN_OPT_CAP);
995 stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
996 stream_putc (s, CAPABILITY_CODE_MP);
997 stream_putc (s, CAPABILITY_CODE_MP_LEN);
998 stream_putw (s, AFI_IP6);
999 stream_putc (s, 0);
1000 stream_putc (s, SAFI_MULTICAST);
1001 }
1002#endif /* HAVE_IPV6 */
1003
1004 /* Route refresh. */
hassoc9502432005-02-01 22:01:48 +00001005 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1006 stream_putc (s, BGP_OPEN_OPT_CAP);
1007 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1008 stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1009 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1010 stream_putc (s, BGP_OPEN_OPT_CAP);
1011 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1012 stream_putc (s, CAPABILITY_CODE_REFRESH);
1013 stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
paul718e3742002-12-13 20:15:29 +00001014
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001015 /* AS4 */
1016 SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1017 stream_putc (s, BGP_OPEN_OPT_CAP);
1018 stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1019 stream_putc (s, CAPABILITY_CODE_AS4);
1020 stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1021 if ( peer->change_local_as )
1022 local_as = peer->change_local_as;
1023 else
1024 local_as = peer->local_as;
1025 stream_putl (s, local_as );
1026
paul718e3742002-12-13 20:15:29 +00001027 /* ORF capability. */
1028 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1029 for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1030 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1031 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1032 {
1033 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1034 bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1035 }
1036
1037 /* Dynamic capability. */
1038 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1039 {
1040 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1041 stream_putc (s, BGP_OPEN_OPT_CAP);
1042 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1043 stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1044 stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1045 }
1046
hasso538621f2004-05-21 09:31:30 +00001047 /* Graceful restart capability */
1048 if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1049 {
1050 SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1051 stream_putc (s, BGP_OPEN_OPT_CAP);
1052 stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
1053 stream_putc (s, CAPABILITY_CODE_RESTART);
1054 stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
1055 stream_putw (s, peer->bgp->restart_time);
1056 }
1057
paul718e3742002-12-13 20:15:29 +00001058 /* Total Opt Parm Len. */
paul9985f832005-02-09 15:51:56 +00001059 len = stream_get_endp (s) - cp - 1;
paul718e3742002-12-13 20:15:29 +00001060 stream_putc_at (s, cp, len);
1061}