Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenBMP support #73

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ AC_CONFIG_FILES([Makefile
lib/bgp/Makefile
lib/bmp/Makefile
lib/mrt/Makefile
tools/Makefile
lib/openbmp/Makefile
tools/Makefile
])
AC_OUTPUT
8 changes: 5 additions & 3 deletions lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
# POSSIBILITY OF SUCH DAMAGE.
#

SUBDIRS = bgp bmp mrt
SUBDIRS = bgp bmp mrt openbmp

AM_CPPFLAGS = -I$(top_srcdir)/ \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/bgp \
-I$(top_srcdir)/lib/bmp \
-I$(top_srcdir)/lib/mrt
-I$(top_srcdir)/lib/mrt \
-I$(top_srcdir)/lib/openbmp

include_HEADERS = \
parsebgp.h \
Expand All @@ -52,7 +53,8 @@ libparsebgp_la_SOURCES = \
libparsebgp_la_LIBADD = \
$(top_builddir)/lib/bgp/libparsebgp_bgp.la \
$(top_builddir)/lib/bmp/libparsebgp_bmp.la \
$(top_builddir)/lib/mrt/libparsebgp_mrt.la
$(top_builddir)/lib/mrt/libparsebgp_mrt.la \
$(top_builddir)/lib/openbmp/libparsebgp_openbmp.la

libparsebgp_la_LDFLAGS = -version-info @LIBPARSEBGP_SHLIB_CURRENT@:@LIBPARSEBGP_SHLIB_REVISION@:@LIBPARSEBGP_SHLIB_AGE@

Expand Down
3 changes: 2 additions & 1 deletion lib/bgp/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ SUBDIRS =

AM_CPPFLAGS = -I$(top_srcdir)/ \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/bmp
-I$(top_srcdir)/lib/bmp \
-I$(top_srcdir)/lib/openbmp

include_HEADERS = \
parsebgp_bgp.h \
Expand Down
3 changes: 2 additions & 1 deletion lib/bmp/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ SUBDIRS =
AM_CPPFLAGS = \
-I$(top_srcdir)/ \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/bgp
-I$(top_srcdir)/lib/bgp \
-I$(top_srcdir)/lib/openbmp

include_HEADERS = \
parsebgp_bmp.h \
Expand Down
3 changes: 2 additions & 1 deletion lib/mrt/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ SUBDIRS =
AM_CPPFLAGS = -I$(top_srcdir)/ \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/bgp \
-I$(top_srcdir)/lib/bmp
-I$(top_srcdir)/lib/bmp \
-I$(top_srcdir)/lib/openbmp

include_HEADERS = parsebgp_mrt.h

Expand Down
47 changes: 47 additions & 0 deletions lib/openbmp/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
# Copyright (C) 2019 The Regents of the University of California.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

SUBDIRS =

AM_CPPFLAGS = \
-I$(top_srcdir)/ \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/bgp \
-I$(top_srcdir)/lib/bmp

include_HEADERS = \
parsebgp_openbmp.h \
parsebgp_openbmp_opts.h

noinst_LTLIBRARIES = libparsebgp_openbmp.la

libparsebgp_openbmp_la_SOURCES = \
parsebgp_openbmp.c \
parsebgp_openbmp.h \
parsebgp_openbmp_opts.c \
parsebgp_openbmp_opts.h

CLEANFILES = *~
241 changes: 241 additions & 0 deletions lib/openbmp/parsebgp_openbmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/*
* Copyright (C) 2019 The Regents of the University of California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "parsebgp_utils.h"
#include "parsebgp_openbmp.h"
#include "parsebgp_bmp.h"

void parsebgp_openbmp_clear_msg(parsebgp_openbmp_msg_t *msg) {
// reset openbmp header values to zero
msg->ver_maj = 0;
msg->ver_min = 0;
msg->flags = 0;
msg->time_sec = 0;
msg->time_usec = 0;
msg->collector_name_len = 0;
memset(msg->collector_name, 0, sizeof(msg->collector_name));
msg->router_name_len = 0;
memset(msg->router_name, 0, sizeof(msg->router_name));

// clear bmp msg too
parsebgp_bmp_clear_msg(msg->bmp_msg);
}

void parsebgp_openbmp_destroy_msg(parsebgp_openbmp_msg_t *msg) {
// free bmp msg
parsebgp_bmp_destroy_msg(msg->bmp_msg);

// now free openbmp msg itself
free(msg);
}

void parsebgp_openbmp_dump_msg(const parsebgp_openbmp_msg_t *msg, int depth) {
// dump openbmp header fields
PARSEBGP_DUMP_INT(depth, "Version major", msg->ver_maj);
PARSEBGP_DUMP_INT(depth, "Version minor", msg->ver_min);
PARSEBGP_DUMP_INT(depth, "Flags", msg->flags);
PARSEBGP_DUMP_INT(depth, "Time.sec", msg->time_sec);
PARSEBGP_DUMP_INT(depth, "Time.usec", msg->time_usec);

PARSEBGP_DUMP_INFO(depth, "Collector name" ": %*s\n",
msg->collector_name_len, msg->collector_name);
PARSEBGP_DUMP_INFO(depth, "Router name" ": %*s\n",
msg->router_name_len, msg->router_name);
PARSEBGP_DUMP_IP(depth, "Router IP", msg->router_afi, msg->router_ip);

// dump bmp msg
parsebgp_bmp_dump_msg(msg->bmp_msg, depth);
}

parsebgp_error_t parsebgp_openbmp_decode(parsebgp_opts_t *opts,
parsebgp_openbmp_msg_t *msg,
const uint8_t *buf, size_t *buf_len) {
// remaining bytes in buffer
size_t len = *buf_len;
// how many bytes are read so far
size_t nread = 0;
int newln = 0;
uint8_t u8;
uint16_t u16;
uint32_t u32;
int name_len = 0;

// we want at least a few bytes to do header checks
if (len < 4) {
*buf_len = 0;
printf("we want at least a few bytes to do header checks\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't use printf's. there are a bunch of utility macros for handling these kinds of parsing failures. in this case you probably just want to return PARSEBGP_PARTIAL_MSG without any kind of logging since this will be a normal failure in the case that the caller hasn't buffered a full message.

return 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return codes should be one of the parsebgp_error_t values

}

// is this an OpenBMP ASCII header (either "text" or "legacy-text")?
if (*buf == 'V') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not support the v1 openbmp headers.

// skip until we find double-newlines
while ((len - nread) > 0) {
if (newln == 2) {
// this is the first byte of the payload
*buf_len = nread - 1;
return 0;
}
if (*buf == '\n') {
newln++;
} else {
newln = 0;
}
nread++;
buf++;
}
// if we reach here, then we've failed to parse the header. just give up
*buf_len = 0;
return 0;
}

// double-check the magic number
if (memcmp(buf, "OBMP", 4) != 0) {
// it's not a known OpenBMP header, assume that it is raw BMP
*buf_len = 0;
printf("it's not a known OpenBMP header, assume that it is raw BMP\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think you just want a printf here.
this code was originally supposed to allow the caller to handle either openbmp-formatted data or raw BMP.
i'm not sure how to support that use case in the libparsebgp model. we could just try parsing the BMP content at this stage, but then we'd need a flag in the openbmp message structure that indicates that only the bmp field is valid. i guess that could work.

return 0;
}
nread += 4;
buf += 4;

// Confirm the version number
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, msg->ver_maj);
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, msg->ver_min);
if (msg->ver_maj != 1 || msg->ver_min != 7) {
printf("Unrecognized OpenBMP header version (%" PRIu8 ".%" PRIu8 ")",
msg->ver_maj, msg->ver_min);
return 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you should be returning an error here, no?
this is probably an instance where you want to use one of the INVALID message macros

}

// skip past the header length and the message length (since we'll parse the
// entire header anyway).
nread += 2 + 4;
buf += 2 + 4;

// read the flags
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, msg->flags);
// check the flags
// we only care about bmp raw messages, which are always router messages
if (!(msg->flags & 0x80)) {
return 0;
}

// check the object type
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, u8);
if (u8 != 12) {
// we only want BMP RAW messages, so skip this one
return 0;
}

// load the time stamps into the record
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, u32);
msg->time_sec = ntohl(u32);
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, u32);
msg->time_usec = ntohl(u32);

// skip past the collector hash
nread += 16;
buf += 16;

// grab the collector admin ID as collector name
// TODO: if there is no admin ID, use the hash
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, u16);
u16 = ntohs(u16);
// maybe truncate the collector name
if (u16 < STR_NAME_LEN) {
name_len = u16;
} else {
name_len = STR_NAME_LEN - 1;
}
// copy the collector name in
if ((len - nread) < u16) {
return -1;
}
msg->collector_name_len = name_len;
memcpy(msg->collector_name, buf, name_len);
msg->collector_name[name_len] = '\0';
nread += u16;
buf += u16;

if ((len - nread) < 32) {
// not enough buffer left for router hash and IP
return -1;
}

// skip past the router hash
nread += 16;
buf += 16;

// grab the router IP
if (msg->flags & 0x40) { // IS_ROUTER_IPV6
msg->router_afi = PARSEBGP_BGP_AFI_IPV6;
} else {
msg->router_afi = PARSEBGP_BGP_AFI_IPV4;
}
// this marco should automatically increment nread and buf
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, msg->router_ip);

// router name
// TODO: if there is no name, or it is "default", use the IP
PARSEBGP_DESERIALIZE_VAL(buf, len - nread, nread, u16);
u16 = ntohs(u16);
// maybe truncate the router name
if (u16 < STR_NAME_LEN) {
name_len = u16;
} else {
name_len = STR_NAME_LEN - 1;
}
// copy the router name in
if ((len - nread) < u16) {
return -1;
}
msg->router_name_len = name_len;
memcpy(msg->router_name, buf, name_len);
msg->router_name[name_len] = '\0';
nread += u16;
buf += u16;

// and then ignore the row count
nread += 4;
buf += 4;

// see whether the raw bmp msg is parsed.
size_t slen = len - nread;
PARSEBGP_MAYBE_MALLOC_ZERO(msg->bmp_msg);
parsebgp_error_t bmp_parse_err = parsebgp_bmp_decode(opts, msg->bmp_msg, buf, &slen);
// return err msg from bmp parsing if any.
if (bmp_parse_err != PARSEBGP_OK) {
return bmp_parse_err;
}
// increment read len
nread += slen;

// set how many bytes were read to parse this openbmp msg.
*buf_len = nread;
// return an openbmp msg was parsed.
return PARSEBGP_OK;
}
Loading