Spin #2 --- proto/bgp/bgp.c | 12 +++++++++ proto/bgp/bgp.h | 2 ++ proto/bgp/packets.c | 73 ++++++++++++++++++++++++++++++++++------------------- 3 files changed, 61 insertions(+), 26 deletions(-)
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index f706e76..2a89c00 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1487,6 +1487,15 @@ bgp_last_errmsg(struct bgp_proto *p) } static const char * +bgp_last_shutmsg(struct bgp_proto *p) +{ + if (p->last_received_shutmsg) + return(p->last_received_shutmsg); + else + return(NULL); +} + +static const char * bgp_state_dsc(struct bgp_proto *p) { if (p->p.proto_state == PS_DOWN) @@ -1580,7 +1589,10 @@ bgp_show_proto_info(struct proto *P) { const char *err1 = bgp_err_classes[p->last_error_class]; const char *err2 = bgp_last_errmsg(p); + const char *msg = bgp_last_shutmsg(p); cli_msg(-1006, " Last error: %s%s", err1, err2); + if (msg) + cli_msg(-1006, " Message: \"%s\"", msg); } } diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index e47a0eb..d958716 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -157,6 +157,8 @@ struct bgp_proto { u8 last_error_class; /* Error class of last error */ u32 last_error_code; /* Error code of last error. BGP protocol errors are encoded as (bgp_err_code << 16 | bgp_err_subcode) */ + byte last_received_shutmsg[129]; /* RFC 8203 */ + #ifdef IPV6 byte *mp_reach_start, *mp_unreach_start; /* Multiprotocol BGP attribute notes */ unsigned mp_reach_len, mp_unreach_len; diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ab87bdc..a44f264 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -1460,9 +1460,9 @@ static struct { { 5, 3, "Unexpected message in Established state" }, { 6, 0, "Cease" }, /* Subcodes are according to [RFC4486] */ { 6, 1, "Maximum number of prefixes reached" }, - { 6, 2, "Administrative shutdown" }, + { 6, 2, "Administrative shutdown" }, /* RFC 8203 can follow */ { 6, 3, "Peer de-configured" }, - { 6, 4, "Administrative reset" }, + { 6, 4, "Administrative reset" }, /* RFC 8203 can follow */ { 6, 5, "Connection rejected" }, { 6, 6, "Other configuration change" }, { 6, 7, "Connection collision resolution" }, @@ -1497,35 +1497,56 @@ bgp_error_dsc(unsigned code, unsigned subcode) 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]; - unsigned i; + const byte *name; + byte *t, argbuf[256]; + unsigned i; + unsigned shutdown_comm_length; - /* Don't report Cease messages generated by myself */ - if (code == 6 && class == BE_BGP_TX) - return; + /* Don't report Cease messages generated by myself */ + if (code == 6 && class == BE_BGP_TX) + return; + + name = bgp_error_dsc(code, subcode); + t = argbuf; + memset(p->last_received_shutmsg, 0, 128 + 1); // clear old RFC 8203 messages - name = bgp_error_dsc(code, subcode); - t = argbuf; - if (len) + if (len) { - *t++ = ':'; - *t++ = ' '; + *t++ = ':'; + *t++ = ' '; - 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)); - goto done; - } - if (len > 16) - len = 16; - for (i=0; i<len; i++) - t += bsprintf(t, "%02x", data[i]); + 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)); + goto done; + } + /* RFC 8203 */ + if ((code == 6) && ((subcode == 2 || subcode == 4)) && (len <= 129)) + { + shutdown_comm_length = data[0]; + if ((shutdown_comm_length <= 128) && (len == shutdown_comm_length + 1)) + { + t += bsprintf(t, "\""); + for (i=1; i<len; i++) + t += bsprintf(t, "%c", data[i]); + t += bsprintf(t, "\""); + memcpy(p->last_received_shutmsg, data + 1, shutdown_comm_length); + goto done; + } + } + else + { + if (len > 16) + len = 16; + for (i=0; i<len; i++) + t += bsprintf(t, "%02x", data[i]); + } } - done: - *t = 0; - log(L_REMOTE "%s: %s: %s%s", p->p.name, msg, name, argbuf); + + done: + *t = 0; + log(L_REMOTE "%s: %s: %s%s", p->p.name, msg, name, argbuf); } static void