Hi OpenBSD,
bgpd(8) as shipped in OpenBSD 6.1 supports draft-ietf-idr-shutdown-07.
The below patch adds support to tcpdump(8) to decode such shutdown
communication.
This is an improved version of the patch proposal I sent in January.
Kind regards,
Job
diff --git a/usr.sbin/tcpdump/print-bgp.c b/usr.sbin/tcpdump/print-bgp.c
index d028d671893..2871b92909f 100644
--- a/usr.sbin/tcpdump/print-bgp.c
+++ b/usr.sbin/tcpdump/print-bgp.c
@@ -228,9 +228,13 @@ static const char *bgpnotify_minor_update[] = {
/* RFC 4486 */
#define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1
+/* draft-ietf-idr-shutdown-07 */
+#define BGP_NOTIFY_MINOR_CEASE_SHUT 2
+#define BGP_NOTIFY_MINOR_CEASE_RESET 4
+#define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN 128
static const char *bgpnotify_minor_cease[] = {
- NULL, "Maximum Number of Prefixes Reached", "Administratively Shutdown",
- "Peer De-configured", "Administratively Reset", "Connection Rejected",
+ NULL, "Maximum Number of Prefixes Reached", "Administrative Shutdown",
+ "Peer De-configured", "Administrative Reset", "Connection Rejected",
"Other Configuration Change", "Connection Collision Resolution",
"Out of Resources",
};
@@ -302,6 +306,13 @@ static const char *afnumber[] = AFNUM_NAME_STR;
sizeof(afnumber)/sizeof(afnumber[0]), (x)))
+static void
+print_hex(const u_char *p, u_int len)
+{
+ while (len--)
+ printf("%02x", *p++);
+}
+
static const char *
num_or_str(const char **table, size_t siz, int value)
{
@@ -996,6 +1007,9 @@ bgp_notification_print(const u_char *dat, int length)
u_int16_t af;
u_int8_t safi;
const u_char *p;
+ uint8_t shutdown_comm_length;
+ uint8_t remainder_offset;
+ char string[128];
TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
@@ -1026,9 +1040,55 @@ bgp_notification_print(const u_char *dat, int length)
printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3));
}
+
+ /*
+ * draft-ietf-idr-shutdown describes a method to send a
+ * message intended for human consumption regarding the
+ * Administrative Shutdown or Reset event. This is called
+ * the "Shutdown Communication". The communication is
+ * UTF-8 encoded and may be no longer than 128 bytes.
+ */
+
+ if ((bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT ||
+ bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) &&
+ (length >= BGP_NOTIFICATION_SIZE + 1)) {
+ p = dat + BGP_NOTIFICATION_SIZE;
+ TCHECK2(*p, 1);
+ shutdown_comm_length = *(p);
+ remainder_offset = 0;
+ /* seems we received garbage, hexdump it all */
+ if (shutdown_comm_length >
+ BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN)
+ printf(", invalid Shutdown Communication
length");
+ else if (shutdown_comm_length == 0) {
+ printf(", empty Shutdown Communication");
+ remainder_offset += 1;
+ }
+ /* a proper shutdown communication */
+ else {
+ TCHECK2(*(p+1), shutdown_comm_length);
+ printf(", Shutdown Communication (length: %u):
\"",
+ shutdown_comm_length);
+ memset(string, 0, 128);
+ memcpy(string, p+1, shutdown_comm_length);
+ safeputs(string);
+ printf("\"");
+ remainder_offset += shutdown_comm_length + 1;
+ }
+ /* if there is trailing data, hexdump it */
+ if (length -
+ (remainder_offset + BGP_NOTIFICATION_SIZE) > 0) {
+ printf(", Data: (length: %u) ",
+ length - (remainder_offset +
+ BGP_NOTIFICATION_SIZE));
+ print_hex(p + remainder_offset, length -
+ (remainder_offset + BGP_NOTIFICATION_SIZE));
+ }
+ }
}
return;
+
trunc:
printf("[|BGP]");
}