summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-rw-r--r--proto/babel/packets.c2
-rw-r--r--proto/bgp/bgp.c48
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/packets.c58
4 files changed, 81 insertions, 29 deletions
diff --git a/proto/babel/packets.c b/proto/babel/packets.c
index 90421836..e9c6d51d 100644
--- a/proto/babel/packets.c
+++ b/proto/babel/packets.c
@@ -146,8 +146,6 @@ struct babel_write_state {
#define TLV_HDR(tlv,t,l) ({ tlv->type = t; tlv->length = l - sizeof(struct babel_tlv); })
#define TLV_HDR0(tlv,t) TLV_HDR(tlv, t, tlv_data[t].min_length)
-#define BYTES(n) ((((uint) n) + 7) / 8)
-
static inline u16
get_time16(const void *p)
{
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 8a6b2f02..b99672f5 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -290,7 +290,7 @@ bgp_update_startup_delay(struct bgp_proto *p)
}
static void
-bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)
+bgp_graceful_close_conn(struct bgp_conn *conn, uint subcode, byte *data, uint len)
{
switch (conn->state)
{
@@ -304,7 +304,7 @@ bgp_graceful_close_conn(struct bgp_conn *conn, unsigned subcode)
case BS_OPENSENT:
case BS_OPENCONFIRM:
case BS_ESTABLISHED:
- bgp_error(conn, 6, subcode, NULL, 0);
+ bgp_error(conn, 6, subcode, data, len);
return;
default:
bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
@@ -340,11 +340,11 @@ bgp_decision(void *vp)
}
void
-bgp_stop(struct bgp_proto *p, unsigned subcode)
+bgp_stop(struct bgp_proto *p, uint subcode, byte *data, uint len)
{
proto_notify_state(&p->p, PS_STOP);
- bgp_graceful_close_conn(&p->outgoing_conn, subcode);
- bgp_graceful_close_conn(&p->incoming_conn, subcode);
+ bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
+ bgp_graceful_close_conn(&p->incoming_conn, subcode, data, len);
ev_schedule(p->event);
}
@@ -420,7 +420,7 @@ bgp_conn_leave_established_state(struct bgp_proto *p)
bgp_free_bucket_table(p);
if (p->p.proto_state == PS_UP)
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
void
@@ -516,7 +516,7 @@ bgp_graceful_restart_timeout(timer *t)
struct bgp_proto *p = t->data;
BGP_TRACE(D_EVENTS, "Neighbor graceful restart timeout");
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
@@ -973,7 +973,7 @@ bgp_neigh_notify(neighbor *n)
BGP_TRACE(D_EVENTS, "Neighbor lost");
bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
/* Perhaps also run bgp_update_startup_delay(p)? */
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
}
else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
@@ -984,7 +984,7 @@ bgp_neigh_notify(neighbor *n)
bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);
if (ps == PS_UP)
bgp_update_startup_delay(p);
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
}
else
@@ -1009,7 +1009,7 @@ bgp_bfd_notify(struct bfd_request *req)
bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
if (ps == PS_UP)
bgp_update_startup_delay(p);
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
}
@@ -1196,7 +1196,11 @@ static int
bgp_shutdown(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
- unsigned subcode = 0;
+ uint subcode = 0;
+
+ char *message = NULL;
+ byte *data = NULL;
+ uint len = 0;
BGP_TRACE(D_EVENTS, "Shutdown requested");
@@ -1214,10 +1218,12 @@ bgp_shutdown(struct proto *P)
case PDC_CMD_DISABLE:
case PDC_CMD_SHUTDOWN:
subcode = 2; // Errcode 6, 2 - administrative shutdown
+ message = P->message;
break;
case PDC_CMD_RESTART:
subcode = 4; // Errcode 6, 4 - administrative reset
+ message = P->message;
break;
case PDC_RX_LIMIT_HIT:
@@ -1242,8 +1248,22 @@ bgp_shutdown(struct proto *P)
bgp_store_error(p, NULL, BE_MAN_DOWN, 0);
p->startup_delay = 0;
- done:
- bgp_stop(p, subcode);
+ /* RFC 8203 - shutdown communication */
+ if (message)
+ {
+ uint msg_len = strlen(message);
+ msg_len = MIN(msg_len, 128);
+
+ /* Buffer will be freed automatically by protocol shutdown */
+ data = mb_alloc(p->p.pool, msg_len + 1);
+ len = msg_len + 1;
+
+ data[0] = msg_len;
+ memcpy(data+1, message, msg_len);
+ }
+
+done:
+ bgp_stop(p, subcode, data, len);
return p->p.proto_state;
}
@@ -1433,7 +1453,7 @@ bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int l
if (code != 6)
{
bgp_update_startup_delay(p);
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
}
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index e47a0eb1..22a150ab 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -212,7 +212,7 @@ void bgp_graceful_restart_done(struct bgp_proto *p);
void bgp_refresh_begin(struct bgp_proto *p);
void bgp_refresh_end(struct bgp_proto *p);
void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
-void bgp_stop(struct bgp_proto *p, unsigned subcode);
+void bgp_stop(struct bgp_proto *p, uint subcode, byte *data, uint len);
struct rte_source *bgp_find_source(struct bgp_proto *p, u32 path_id);
struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index ab87bdcc..af3b15b5 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -1494,38 +1494,72 @@ bgp_error_dsc(unsigned code, unsigned subcode)
return buff;
}
+/* RFC 8203 - shutdown communication message */
+static int
+bgp_handle_message(struct bgp_proto *p, byte *data, uint len, byte **bp)
+{
+ byte *msg = data + 1;
+ uint msg_len = data[0];
+ uint i;
+
+ /* Handle zero length message */
+ if (msg_len == 0)
+ return 1;
+
+ /* Handle proper message */
+ if ((msg_len > 128) && (msg_len + 1 > len))
+ return 0;
+
+ /* Some elementary cleanup */
+ for (i = 0; i < msg_len; i++)
+ if (msg[i] < ' ')
+ msg[i] = ' ';
+
+ proto_set_message(&p->p, msg, msg_len);
+ *bp += bsprintf(*bp, ": \"%s\"", p->p.message);
+ return 1;
+}
+
void
bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len)
{
- const byte *name;
- byte *t, argbuf[36];
+ byte argbuf[256], *t = argbuf;
unsigned i;
/* Don't report Cease messages generated by myself */
if (code == 6 && class == BE_BGP_TX)
return;
- name = bgp_error_dsc(code, subcode);
- t = argbuf;
+ /* Reset shutdown message */
+ if ((code == 6) && ((subcode == 2) || (subcode == 4)))
+ proto_set_message(&p->p, NULL, 0);
+
if (len)
{
- *t++ = ':';
- *t++ = ' ';
-
+ /* Bad peer AS - we would like to print the AS */
if ((code == 2) && (subcode == 2) && ((len == 2) || (len == 4)))
{
- /* Bad peer AS - we would like to print the AS */
- t += bsprintf(t, "%d", (len == 2) ? get_u16(data) : get_u32(data));
+ t += bsprintf(t, ": %u", (len == 2) ? get_u16(data) : get_u32(data));
goto done;
}
+
+ /* RFC 8203 - shutdown communication */
+ if (((code == 6) && ((subcode == 2) || (subcode == 4))))
+ if (bgp_handle_message(p, data, len, &t))
+ goto done;
+
+ *t++ = ':';
+ *t++ = ' ';
if (len > 16)
len = 16;
for (i=0; i<len; i++)
t += bsprintf(t, "%02x", data[i]);
}
- done:
+
+done:
*t = 0;
- log(L_REMOTE "%s: %s: %s%s", p->p.name, msg, name, argbuf);
+ const byte *dsc = bgp_error_dsc(code, subcode);
+ log(L_REMOTE "%s: %s: %s%s", p->p.name, msg, dsc, argbuf);
}
static void
@@ -1571,7 +1605,7 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, uint len)
if (err)
{
bgp_update_startup_delay(p);
- bgp_stop(p, 0);
+ bgp_stop(p, 0, NULL, 0);
}
}