Skip to content
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
10 changes: 10 additions & 0 deletions lib/bgpstream_bgpdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ char *bgpstream_record_elem_bgpdump_snprintf(char *buf, size_t len,
ssize_t c = 0; /* < how many chars were written */
char *buf_p = buf;

/* The original bgpdump tool does not represent End-of-RIB markers in its
* output (an EoR is an empty UPDATE, which it silently drops). To stay
* faithful to that format we emit nothing for them. Callers should skip empty
* output. */
if (elem->type == BGPSTREAM_ELEM_TYPE_END_OF_RIB) {
if (len > 0)
buf[0] = '\0';
return buf;
}

/* Record type */
switch (elem->type) {
case BGPSTREAM_ELEM_TYPE_RIB:
Expand Down
25 changes: 25 additions & 0 deletions lib/bgpstream_elem.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ int bgpstream_elem_type_snprintf(char *buf, size_t len,
case BGPSTREAM_ELEM_TYPE_ANNOUNCEMENT: ch = 'A'; break;
case BGPSTREAM_ELEM_TYPE_WITHDRAWAL: ch = 'W'; break;
case BGPSTREAM_ELEM_TYPE_PEERSTATE: ch = 'S'; break;
case BGPSTREAM_ELEM_TYPE_END_OF_RIB: ch = 'E'; break;
default:
if (len > 0)
buf[0] = '\0';
Expand Down Expand Up @@ -378,6 +379,30 @@ char *bgpstream_elem_custom_snprintf(char *buf, size_t len,
/* END OF LINE */
break;

case BGPSTREAM_ELEM_TYPE_END_OF_RIB:

/* PREFIX (AFI indicator) */
if (bgpstream_pfx_snprintf(buf_p, B_REMAIN, &(elem->prefix)) == NULL) {
if (errno != ENOSPC)
bgpstream_log(BGPSTREAM_LOG_ERR, "Malformed prefix (E)");
return NULL;
}
SEEK_STR_END;
ADD_PIPE;
/* NEXT HOP (empty) */
ADD_PIPE;
/* AS PATH (empty) */
ADD_PIPE;
/* ORIGIN AS (empty) */
ADD_PIPE;
/* COMMUNITIES (empty) */
ADD_PIPE;
/* OLD STATE (empty) */
ADD_PIPE;
/* NEW STATE (empty) */
/* END OF LINE */
break;

default:
bgpstream_log(BGPSTREAM_LOG_ERR, "Error during elem processing");
return NULL;
Expand Down
3 changes: 3 additions & 0 deletions lib/bgpstream_elem.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ typedef enum {
/** Peer state change */
BGPSTREAM_ELEM_TYPE_PEERSTATE = 4,

/** End-of-RIB marker (RFC 4724) */
BGPSTREAM_ELEM_TYPE_END_OF_RIB = 5,

} bgpstream_elem_type_t;

typedef struct struct_bgpstream_annotations_t {
Expand Down
2 changes: 2 additions & 0 deletions lib/bgpstream_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ int bgpstream_filter_mgr_filter_add(bgpstream_filter_mgr_t *this,
this->elemtype_mask |= (BGPSTREAM_FILTER_ELEM_TYPE_WITHDRAWAL);
} else if (strcmp(filter_value, "peerstates") == 0) {
this->elemtype_mask |= (BGPSTREAM_FILTER_ELEM_TYPE_PEERSTATE);
} else if (strcmp(filter_value, "endofrib") == 0) {
this->elemtype_mask |= (BGPSTREAM_FILTER_ELEM_TYPE_END_OF_RIB);
} else {
bgpstream_log(BGPSTREAM_LOG_ERR,
"unknown element type '%s'", filter_value);
Expand Down
1 change: 1 addition & 0 deletions lib/bgpstream_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#define BGPSTREAM_FILTER_ELEM_TYPE_ANNOUNCEMENT 0x2
#define BGPSTREAM_FILTER_ELEM_TYPE_WITHDRAWAL 0x4
#define BGPSTREAM_FILTER_ELEM_TYPE_PEERSTATE 0x8
#define BGPSTREAM_FILTER_ELEM_TYPE_END_OF_RIB 0x10

/* hash table community filter:
* community -> filter mask (asn only, value only, both) */
Expand Down
5 changes: 5 additions & 0 deletions lib/bgpstream_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ static int elem_check_filters(bgpstream_record_t *record,
!(filter_mgr->elemtype_mask & BGPSTREAM_FILTER_ELEM_TYPE_WITHDRAWAL)) {
return 0;
}

if (elem->type == BGPSTREAM_ELEM_TYPE_END_OF_RIB &&
!(filter_mgr->elemtype_mask & BGPSTREAM_FILTER_ELEM_TYPE_END_OF_RIB)) {
return 0;
}
}

/* Checking peer ASNs: if the filter is on and the peer asn is not in the
Expand Down
57 changes: 57 additions & 0 deletions lib/formats/bgpstream_parsebgp_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,48 @@ static int handle_prefix(bgpstream_elem_t *elem,
} \
} while (0)

// Detect an RFC 4724 End-of-RIB marker and, if found, populate `elem` as an
// END_OF_RIB elem whose prefix encodes the AFI (0.0.0.0/0 for IPv4 unicast,
// ::/0 for IPv6 unicast). Returns 1 if an EoR was detected and `elem` was
// populated, 0 otherwise. The caller guarantees the UPDATE carries no
// withdrawn/announced NLRIs before calling this.
Comment thread
alistairking marked this conversation as resolved.
Outdated
static int handle_end_of_rib(bgpstream_elem_t *elem,
parsebgp_bgp_update_t *update)
{
// a 16-byte zeroed source so we can build the 0.0.0.0/0 or ::/0 prefix that
// encodes the EoR AFI
static const uint8_t zero_addr[16] = { 0 };

Comment thread
alistairking marked this conversation as resolved.
// IPv4 unicast EoR: a completely empty UPDATE (no NLRIs, no path attrs)
if (update->path_attrs.attrs_cnt == 0) {
elem->type = BGPSTREAM_ELEM_TYPE_END_OF_RIB;
bgpstream_ipv4_addr_init(&elem->prefix.address, zero_addr);
elem->prefix.mask_len = 0;
return 1;
}

// IPv6 (or other AFI) unicast EoR: an MP_UNREACH_NLRI attribute carrying zero
// withdrawn NLRIs with the unicast SAFI
parsebgp_bgp_update_path_attr_t *mp_unreach_attr =
&update->path_attrs.attrs[PARSEBGP_BGP_PATH_ATTR_TYPE_MP_UNREACH_NLRI];
if (mp_unreach_attr->type != PARSEBGP_BGP_PATH_ATTR_TYPE_MP_UNREACH_NLRI) {
return 0;
}
parsebgp_bgp_update_mp_unreach_t *mp_unreach = mp_unreach_attr->data.mp_unreach;
if (mp_unreach->withdrawn_nlris_cnt != 0 ||
mp_unreach->safi != PARSEBGP_BGP_SAFI_UNICAST) {
return 0;
}
Comment thread
alistairking marked this conversation as resolved.
elem->type = BGPSTREAM_ELEM_TYPE_END_OF_RIB;
if (mp_unreach->afi == PARSEBGP_BGP_AFI_IPV6) {
bgpstream_ipv6_addr_init(&elem->prefix.address, zero_addr);
} else {
bgpstream_ipv4_addr_init(&elem->prefix.address, zero_addr);
}
elem->prefix.mask_len = 0;
Comment thread
alistairking marked this conversation as resolved.
Outdated
return 1;
}

int bgpstream_parsebgp_process_update(bgpstream_parsebgp_upd_state_t *upd_state,
bgpstream_elem_t *elem,
parsebgp_bgp_msg_t *bgp)
Expand All @@ -325,6 +367,11 @@ int bgpstream_parsebgp_process_update(bgpstream_parsebgp_upd_state_t *upd_state,
return 0;
}

// the message claims to be an UPDATE, but carries no UPDATE payload
if (update == NULL) {
return 0;
}

// how many native withdrawals will we process?
upd_state->withdrawal_v4_cnt = update->withdrawn_nlris.prefixes_cnt;

Expand Down Expand Up @@ -355,6 +402,16 @@ int bgpstream_parsebgp_process_update(bgpstream_parsebgp_upd_state_t *upd_state,
// are we at end-of-elems?
if (upd_state->withdrawal_v4_cnt == 0 && upd_state->withdrawal_v6_cnt == 0 &&
upd_state->announce_v4_cnt == 0 && upd_state->announce_v6_cnt == 0) {

// Check if this is an End-of-RIB marker (RFC 4724). We only emit a single
// EoR elem per record, so guard with eor_done.
if (upd_state->eor_done == 0 && update != NULL) {
upd_state->eor_done = 1;
if (handle_end_of_rib(elem, update) != 0) {
return 1;
}
}
Comment thread
alistairking marked this conversation as resolved.

return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions lib/formats/bgpstream_parsebgp_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ typedef struct bgpstream_parsebgp_upd_state {
// has the BGP4MP state been prepared
int ready;

// has the End-of-RIB check been performed
int eor_done;

// how many native (IPv4) withdrawals still to yield
int withdrawal_v4_cnt;
int withdrawal_v4_idx;
Expand Down
1 change: 1 addition & 0 deletions lib/formats/bs_format_rislive.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@ void bs_format_rislive_clear_data(bgpstream_format_t *format, void *data)
bgpstream_elem_clear(rd->elem);
rd->end_of_elems = 0;
rd->next_re = 0;
rd->msg_type = 0;
bgpstream_parsebgp_upd_state_reset(&rd->upd_state);
parsebgp_clear_msg(rd->msg);
}
Expand Down
9 changes: 8 additions & 1 deletion tools/bgpreader.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"<origin-AS>|<communities>|<old-state>|<new-state>\n" \
"#\n" \
"# <rec-type>: R RIB, U Update\n" \
"# <elem-type>: R RIB, A announcement, W withdrawal, S state message\n" \
"# <elem-type>: R RIB, A announcement, W withdrawal, S state message,\n" \
"# E end-of-RIB marker\n" \
"#\n"

enum rpki_options {
Expand Down Expand Up @@ -771,6 +772,12 @@ static int print_elem_bgpdump(bgpstream_record_t *record,
return -1;
}

/* Some elem types (e.g. End-of-RIB markers) have no representation in the
* bgpdump output format and produce an empty string; skip them. */
if (buf[0] == '\0') {
return 0;
}

printf("%s\n", buf);
return 0;
}