summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_msg_read.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_msg_read.c')
-rw-r--r--bgpd/bgp_msg_read.c167
1 files changed, 131 insertions, 36 deletions
diff --git a/bgpd/bgp_msg_read.c b/bgpd/bgp_msg_read.c
index 014860cc..020f2f0c 100644
--- a/bgpd/bgp_msg_read.c
+++ b/bgpd/bgp_msg_read.c
@@ -19,9 +19,22 @@
* Boston, MA 02111-1307, USA.
*/
-#include "bgp_msg_read.h"
+#include <zebra.h>
+
+#include "bgpd/bgp_common.h"
+#include "bgpd/bgp_msg_read.h"
+#include "bgpd/bgp_open.h"
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_session.h"
+#include "bgpd/bgp_open_state.h"
+#include "bgpd/bgp_fsm.h"
+
+
/* prototypes */
+static int bgp_msg_marker_all_one (struct stream *s, int length);
static int bgp_msg_open_receive (bgp_connection connection, bgp_size_t size);
static as_t bgp_msg_peek_for_as4_capability (bgp_connection connection,
u_char length);
@@ -33,7 +46,9 @@ static int bgp_msg_capability_parse (bgp_connection connection, size_t length,
u_char **error);
static int bgp_msg_capability_mp (bgp_connection connection,
struct capability_header *hdr);
-static int bgp_capability_orf_entry (bgp_connection connection,
+static int bgp_msg_capability_restart (bgp_connection connection,
+ struct capability_header *caphdr);
+static int bgp_msg_capability_orf_entry (bgp_connection connection,
struct capability_header *hdr);
static int bgp_msg_capability_orf (bgp_connection connection,
struct capability_header *hdr);
@@ -75,7 +90,7 @@ bgp_msg_check_header(bgp_connection connection)
/* Marker check */
if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
- && ! bgp_marker_all_one (connection->ibuf, BGP_MARKER_SIZE))
+ && ! bgp_msg_marker_all_one (connection->ibuf, BGP_MARKER_SIZE))
{
bgp_msg_notify_send (connection, bgp_session_eInvalid_msg,
BGP_NOTIFY_HEADER_ERR,
@@ -128,19 +143,31 @@ bgp_msg_check_header(bgp_connection connection)
return size - BGP_HEADER_SIZE;
}
+/* Marker check. */
+static int
+bgp_msg_marker_all_one (struct stream *s, int length)
+{
+ int i;
+
+ for (i = 0; i < length; i++)
+ if (s->data[i] != 0xff)
+ return 0;
+
+ return 1;
+}
+
/* Deal with the BGP message. MUST remove from ibuf before returns ! */
void
bgp_msg_dispatch(bgp_connection connection)
{
u_char type = 0;
bgp_size_t size;
- int result = 0;
/* Get size and type again. */
size = stream_getw_from (connection->ibuf, BGP_MARKER_SIZE);
type = stream_getc_from (connection->ibuf, BGP_MARKER_SIZE + 2);
- size = size - BGP_HEADER_SIZE;
+ size -= BGP_HEADER_SIZE;
/* Read rest of the packet and call each sort of packet routine */
switch (type)
@@ -176,7 +203,9 @@ bgp_msg_dispatch(bgp_connection connection)
assert(0); /* types already validated */
}
- /* TODO: remove message from ibuf */
+ /* remove message from ibuf */
+ if (connection->ibuf)
+ stream_reset (connection->ibuf);
}
/* Receive BGP open packet and parse it into the session's
@@ -190,9 +219,7 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
int ret;
u_char version;
u_char optlen;
- u_int16_t holdtime;
- u_int16_t send_holdtime;
- as_t remote_as;
+ as_t remote_as = 0;
as_t as4 = 0;
struct in_addr remote_id;
int capability;
@@ -204,7 +231,8 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
assert(session);
/* To receive the parsed open message */
- session->open_recv = open_recv = bgp_open_state_init_new(session->open_recv);
+ session->open_recv = bgp_open_state_init_new(session->open_recv);
+ open_recv = session->open_recv;
/* Parse open packet. */
version = stream_getc (connection->ibuf);
@@ -235,7 +263,7 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
}
/* Just in case we have a silly peer who sends AS4 capability set to 0 */
- if (open_rcvd->can_as4 && !as4)
+ if (open_recv->can_as4 && !as4)
{
zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
session->host);
@@ -274,7 +302,7 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
{
/* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
/* If we have got the capability, peer->as4cap must match remote_as */
- if (open_rcvd->can_as4 && as4 != remote_as)
+ if (open_recv->can_as4 && as4 != remote_as)
{
/* raise error, log this, close session */
zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
@@ -288,7 +316,7 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
}
/* Set remote router-id */
- open_recv->bgp_id = ntohl(remote_id);
+ open_recv->bgp_id = remote_id.s_addr;
/* Peer BGP version check. */
if (version != BGP_VERSION_4)
@@ -304,7 +332,8 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
return -1;
}
- /* Check neighbor as number. */
+ /* TODO: How? Check neighbor as number. */
+#if 0
if (remote_as != session->as)
{
if (BGP_DEBUG (normal, NORMAL))
@@ -316,6 +345,7 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
notify_data_remote_as, 2);
return -1;
}
+#endif
/* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
calculate the value of the Hold Timer by using the smaller of its
@@ -334,7 +364,7 @@ bgp_msg_open_receive (bgp_connection connection, bgp_size_t size)
/* Open option part parse. */
if (optlen != 0)
{
- ret = bgp_open_option_parse (connection, optlen, &open_recv->can_capability);
+ ret = bgp_msg_open_option_parse (connection, optlen, &open_recv->can_capability);
if (ret < 0)
return ret;
}
@@ -433,7 +463,7 @@ bgp_msg_peek_for_as4_capability (bgp_connection connection, u_char length)
if (BGP_DEBUG (as4, AS4))
zlog_info ("[AS4] found AS4 capability, about to parse");
as4 = stream_getl (connection->ibuf);
- open_recv->can_as4 = 1;
+ session->open_recv->can_as4 = 1;
goto end;
}
@@ -456,7 +486,7 @@ bgp_msg_open_option_parse (bgp_connection connection, u_char length, int *capabi
u_char error_data[BGP_MAX_PACKET_SIZE];
struct stream *s = connection->ibuf;
size_t end = stream_get_getp (s) + length;
- bpg_session session = connection->session;
+ bgp_session session = connection->session;
assert(session);
ret = 0;
@@ -509,7 +539,7 @@ bgp_msg_open_option_parse (bgp_connection connection, u_char length, int *capabi
ret = -1;
break;
case BGP_OPEN_OPT_CAP:
- ret = bgp_msg_capability_parse (conection, opt_length, &error);
+ ret = bgp_msg_capability_parse (connection, opt_length, &error);
*capability = 1;
break;
default:
@@ -544,7 +574,7 @@ bgp_msg_open_option_parse (bgp_connection connection, u_char length, int *capabi
/* Check local capability does not negotiated with remote
peer. */
- if (open_recv->can_mp_ext != open_send->can_mp_ext)
+ if (session->open_recv->can_mp_ext != session->open_send->can_mp_ext)
{
bgp_msg_notify_send (connection, bgp_session_eOpen_reject,
BGP_NOTIFY_OPEN_ERR,
@@ -557,7 +587,7 @@ bgp_msg_open_option_parse (bgp_connection connection, u_char length, int *capabi
error. */
if (*capability && ! session->cap_override)
{
- if (open_recv->can_mp_ext == 0)
+ if (session->open_recv->can_mp_ext == 0)
{
plog_err (session->log, "%s [Error] No common capability", session->host);
@@ -694,7 +724,7 @@ bgp_msg_capability_parse (bgp_connection connection, size_t length, u_char **err
return -1;
break;
case CAPABILITY_CODE_DYNAMIC:
- open->recv->can_dynamic = 1;
+ open_recv->can_dynamic = 1;
break;
case CAPABILITY_CODE_AS4:
/* Already handled as a special-case parsing of the capabilities
@@ -767,7 +797,74 @@ bgp_msg_capability_mp (bgp_connection connection, struct capability_header *hdr)
}
static int
-bgp_capability_orf_entry (bgp_connection connection, struct capability_header *hdr)
+bgp_msg_capability_restart (bgp_connection connection, struct capability_header *caphdr)
+{
+ struct stream *s = connection->ibuf;
+ bgp_session session = connection->session;
+ bgp_open_state open_recv = session->open_recv;
+ u_int16_t restart_flag_time;
+ int restart_bit = 0;
+ size_t end = stream_get_getp (s) + caphdr->length;
+
+ open_recv->can_g_restart = 1;
+ restart_flag_time = stream_getw(s);
+ if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
+ restart_bit = 1;
+ UNSET_FLAG (restart_flag_time, 0xF000);
+ open_recv->restart_time = restart_flag_time;
+
+ if (BGP_DEBUG (normal, NORMAL))
+ {
+ zlog_debug ("%s OPEN has Graceful Restart capability", session->host);
+ zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
+ session->host, restart_bit ? " " : " not ",
+ open_recv->restart_time);
+ }
+
+ /* TODO restart */
+#if 0
+ while (stream_get_getp (s) + 4 < end)
+ {
+ afi_t afi = stream_getw (s);
+ safi_t safi = stream_getc (s);
+ u_char flag = stream_getc (s);
+
+ if (!bgp_afi_safi_valid_indices (afi, &safi))
+ {
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
+ " Ignore the Graceful Restart capability",
+ peer->host, afi, safi);
+ }
+ else if (!peer->afc[afi][safi])
+ {
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
+ " Ignore the Graceful Restart capability",
+ peer->host, afi, safi);
+ }
+ else
+ {
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s Address family %s is%spreserved", peer->host,
+ afi_safi_print (afi, safi),
+ CHECK_FLAG (peer->af_cap[afi][safi],
+ PEER_CAP_RESTART_AF_PRESERVE_RCV)
+ ? " " : " not ");
+
+ SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
+ if (CHECK_FLAG (flag, RESTART_F_BIT))
+ SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
+
+ }
+ }
+#endif
+ return 0;
+}
+
+
+static int
+bgp_msg_capability_orf_entry (bgp_connection connection, struct capability_header *hdr)
{
struct stream *s = connection->ibuf;
struct capability_orf_entry entry;
@@ -775,8 +872,6 @@ bgp_capability_orf_entry (bgp_connection connection, struct capability_header *h
safi_t safi;
u_char type;
u_char mode;
- u_int16_t sm_cap = 0; /* capability send-mode receive */
- u_int16_t rm_cap = 0; /* capability receive-mode receive */
int i;
bgp_session session = connection->session;
qafx_bit_t qb;
@@ -784,7 +879,7 @@ bgp_capability_orf_entry (bgp_connection connection, struct capability_header *h
assert(session);
/* ORF Entry header */
- bgp_msg_capability_mp_data (s, &entry.mpc);
+ bgp_capability_mp_data (s, &entry.mpc);
entry.num = stream_getc (s);
afi = entry.mpc.afi;
safi = entry.mpc.safi;
@@ -876,9 +971,9 @@ bgp_capability_orf_entry (bgp_connection connection, struct capability_header *h
if (hdr->code == CAPABILITY_CODE_ORF)
- open_recv->can_orf_prefix |= bgp_cap_form_new;
+ session->open_recv->can_orf_prefix |= bgp_cap_form_new;
else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
- open_recv->can_orf_prefix |= bgp_cap_form_old;
+ session->open_recv->can_orf_prefix |= bgp_cap_form_old;
else
{
bgp_msg_capability_orf_not_support (session->host, afi, safi, type, mode);
@@ -889,14 +984,14 @@ bgp_capability_orf_entry (bgp_connection connection, struct capability_header *h
switch (mode)
{
case ORF_MODE_BOTH:
- open_recv->can_orf_prefix_send |= qb;
- open_recv->can_orf_prefix_recv |= qb;
+ session->open_recv->can_orf_prefix_send |= qb;
+ session->open_recv->can_orf_prefix_recv |= qb;
break;
case ORF_MODE_SEND:
- open_recv->can_orf_prefix_send |= qb;
+ session->open_recv->can_orf_prefix_send |= qb;
break;
case ORF_MODE_RECEIVE:
- open_recv->can_orf_prefix_recv |= qb;
+ session->open_recv->can_orf_prefix_recv |= qb;
break;
}
}
@@ -939,7 +1034,7 @@ bgp_msg_capability_orf_not_support (char *host, afi_t afi, safi_t safi,
static int
bgp_msg_update_receive (bgp_connection connection, bgp_size_t size)
{
- /* TODO: got update packet, now what? */
+ bgp_session_update_recv(connection->session, stream_dup(connection->ibuf));
bgp_fsm_event(connection, bgp_fsm_Receive_UPDATE_message);
return 0;
}
@@ -969,9 +1064,9 @@ bgp_msg_notify_receive (bgp_connection connection, bgp_size_t size)
bgp_nom_subcode_t subcode = stream_getc (connection->ibuf);
bgp_size_t expect = size - 2;
- notification = bgp_notify_new(code, subcode, datalen);
+ notification = bgp_notify_new(code, subcode, expect);
notification = bgp_notify_append_data(notification,
- stream_pnt(connection->ibuf), datalen);
+ stream_pnt(connection->ibuf), expect);
bgp_fsm_notification_exception(connection, notification);
}
@@ -982,7 +1077,7 @@ bgp_msg_notify_send (bgp_connection connection, bgp_session_event_t except,
bgp_nom_code_t code, bgp_nom_subcode_t sub_code)
{
bgp_notify notification;
- notification = bgp_notify_new(code, subcode, 0);
+ notification = bgp_notify_new(code, sub_code, 0);
bgp_fsm_raise_exception(connection, except, notification);
}
@@ -994,7 +1089,7 @@ bgp_msg_notify_send_with_data (bgp_connection connection,
u_char *data, size_t datalen)
{
bgp_notify notification;
- notification = bgp_notify_new(code, subcode, datalen);
+ notification = bgp_notify_new(code, sub_code, datalen);
notification = bgp_notify_append_data(notification, data, datalen);
bgp_fsm_raise_exception(connection, except, notification);
}