|
@@ -42,6 +42,8 @@ this license is included with libbgpdump.
|
|
#include <assert.h>
|
|
#include <assert.h>
|
|
|
|
|
|
void bgpdump_free_attr(attributes_t *attr);
|
|
void bgpdump_free_attr(attributes_t *attr);
|
|
|
|
+static BGPDUMP_ENTRY* bgpdump_entry_create(BGPDUMP *dump);
|
|
|
|
+static int process_mrtd_bgp(struct mstream *s, BGPDUMP_ENTRY *entry);
|
|
static int process_mrtd_table_dump(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_mrtd_table_dump(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_mrtd_table_dump_v2(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_mrtd_table_dump_v2(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
@@ -58,16 +60,16 @@ static int process_zebra_bgp_message_notify(struct mstream *s,BGPDUMP_ENTRY *
|
|
static int process_zebra_bgp_entry(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_zebra_bgp_entry(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_zebra_bgp_snapshot(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
static int process_zebra_bgp_snapshot(struct mstream *s,BGPDUMP_ENTRY *entry);
|
|
|
|
|
|
-static attributes_t *process_attributes(struct mstream *s, u_int8_t asn_len, struct zebra_incomplete *incomplete);
|
|
|
|
|
|
+static attributes_t *process_attributes(struct mstream *s, u_int8_t asn_len, struct zebra_incomplete *incomplete, int is_addp);
|
|
static void process_attr_aspath_string(struct aspath *as);
|
|
static void process_attr_aspath_string(struct aspath *as);
|
|
static char aspath_delimiter_char (u_char type, u_char which);
|
|
static char aspath_delimiter_char (u_char type, u_char which);
|
|
static void process_attr_community_string(struct community *com);
|
|
static void process_attr_community_string(struct community *com);
|
|
|
|
|
|
-static void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete);
|
|
|
|
-static void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete);
|
|
|
|
-static int read_prefix_list(struct mstream *s, u_int16_t af, struct prefix *prefixes, struct zebra_incomplete *incomplete);
|
|
|
|
|
|
+static void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp);
|
|
|
|
+static void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp);
|
|
|
|
+static int read_prefix_list(struct mstream *s, u_int16_t af, struct prefix *prefixes, struct zebra_incomplete *incomplete, int is_addp);
|
|
|
|
|
|
-static as_t read_asn(struct mstream *s, as_t *asn, u_int8_t len);
|
|
|
|
|
|
+static as_t read_asn(struct mstream *s, u_int8_t len);
|
|
static struct aspath *create_aspath(u_int16_t len, u_int8_t asn_len);
|
|
static struct aspath *create_aspath(u_int16_t len, u_int8_t asn_len);
|
|
static void aspath_error(struct aspath *as);
|
|
static void aspath_error(struct aspath *as);
|
|
static int check_new_aspath(struct aspath *aspath);
|
|
static int check_new_aspath(struct aspath *aspath);
|
|
@@ -75,8 +77,6 @@ static void process_asn32_trans(attributes_t *attr, u_int8_t asn_len);
|
|
static struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath);
|
|
static struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath);
|
|
static void asn32_expand_16_to_32(char *dst, char *src, int len);
|
|
static void asn32_expand_16_to_32(char *dst, char *src, int len);
|
|
|
|
|
|
-BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE *table_dump_v2_peer_index_table = NULL;
|
|
|
|
-
|
|
|
|
#if defined(linux)
|
|
#if defined(linux)
|
|
static size_t strlcat(char *dst, const char *src, size_t size);
|
|
static size_t strlcat(char *dst, const char *src, size_t size);
|
|
#endif
|
|
#endif
|
|
@@ -93,10 +93,17 @@ BGPDUMP *bgpdump_open_dump(const char *filename) {
|
|
perror("can't open dumpfile");
|
|
perror("can't open dumpfile");
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
-
|
|
|
|
BGPDUMP *this_dump = malloc(sizeof(BGPDUMP));
|
|
BGPDUMP *this_dump = malloc(sizeof(BGPDUMP));
|
|
|
|
+ if (this_dump == NULL) {
|
|
|
|
+ perror("malloc");
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
strcpy(this_dump->filename, "[STDIN]");
|
|
strcpy(this_dump->filename, "[STDIN]");
|
|
if(filename && strcmp(filename, "-")) {
|
|
if(filename && strcmp(filename, "-")) {
|
|
|
|
+ if (strlen(filename) >= BGPDUMP_MAX_FILE_LEN - 1) {
|
|
|
|
+ fprintf (stderr, "File name %s is too long.\n", filename);
|
|
|
|
+ exit(1);
|
|
|
|
+ }
|
|
strcpy(this_dump->filename, filename);
|
|
strcpy(this_dump->filename, filename);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -104,38 +111,53 @@ BGPDUMP *bgpdump_open_dump(const char *filename) {
|
|
this_dump->eof=0;
|
|
this_dump->eof=0;
|
|
this_dump->parsed = 0;
|
|
this_dump->parsed = 0;
|
|
this_dump->parsed_ok = 0;
|
|
this_dump->parsed_ok = 0;
|
|
|
|
+ // peer index table shared among entries
|
|
|
|
+ this_dump->table_dump_v2_peer_index_table = NULL;
|
|
|
|
|
|
return this_dump;
|
|
return this_dump;
|
|
}
|
|
}
|
|
|
|
|
|
void bgpdump_close_dump(BGPDUMP *dump) {
|
|
void bgpdump_close_dump(BGPDUMP *dump) {
|
|
- if(dump!=NULL) {
|
|
|
|
|
|
|
|
- if(table_dump_v2_peer_index_table){
|
|
|
|
- if(table_dump_v2_peer_index_table->entries) {
|
|
|
|
- free(table_dump_v2_peer_index_table->entries);
|
|
|
|
- table_dump_v2_peer_index_table->entries = NULL;
|
|
|
|
- }
|
|
|
|
- free(table_dump_v2_peer_index_table);
|
|
|
|
- table_dump_v2_peer_index_table = NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ if(dump == NULL) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(dump->table_dump_v2_peer_index_table){
|
|
|
|
+ free(dump->table_dump_v2_peer_index_table->entries);
|
|
|
|
+ }
|
|
|
|
+ free(dump->table_dump_v2_peer_index_table);
|
|
cfr_close(dump->f);
|
|
cfr_close(dump->f);
|
|
- free(dump);
|
|
|
|
|
|
+ free(dump);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+BGPDUMP_ENTRY* bgpdump_entry_create(BGPDUMP *dump){
|
|
|
|
+ BGPDUMP_ENTRY *this_entry = malloc(sizeof(BGPDUMP_ENTRY));
|
|
|
|
+ if(this_entry == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
+ memset(this_entry, 0, sizeof(BGPDUMP_ENTRY));
|
|
|
|
+ this_entry->dump = dump;
|
|
|
|
+ return this_entry;
|
|
}
|
|
}
|
|
|
|
|
|
BGPDUMP_ENTRY* bgpdump_read_next(BGPDUMP *dump) {
|
|
BGPDUMP_ENTRY* bgpdump_read_next(BGPDUMP *dump) {
|
|
assert(dump);
|
|
assert(dump);
|
|
|
|
|
|
- BGPDUMP_ENTRY *this_entry=NULL;
|
|
|
|
struct mstream s;
|
|
struct mstream s;
|
|
u_char *buffer;
|
|
u_char *buffer;
|
|
int ok=0;
|
|
int ok=0;
|
|
- u_int32_t bytes_read;
|
|
|
|
|
|
+ u_int32_t bytes_read, t;
|
|
|
|
|
|
- this_entry = malloc(sizeof(BGPDUMP_ENTRY));
|
|
|
|
|
|
+ BGPDUMP_ENTRY *this_entry = bgpdump_entry_create(dump);
|
|
|
|
+ if(this_entry == NULL) {
|
|
|
|
+ err("%s: out of memmory", __func__);
|
|
|
|
+ dump->eof = 1;
|
|
|
|
+ return(NULL);
|
|
|
|
+ }
|
|
|
|
|
|
- bytes_read = cfr_read_n(dump->f, &(this_entry->time), 4);
|
|
|
|
|
|
+ bytes_read = cfr_read_n(dump->f, &t, 4);
|
|
bytes_read += cfr_read_n(dump->f, &(this_entry->type), 2);
|
|
bytes_read += cfr_read_n(dump->f, &(this_entry->type), 2);
|
|
bytes_read += cfr_read_n(dump->f, &(this_entry->subtype), 2);
|
|
bytes_read += cfr_read_n(dump->f, &(this_entry->subtype), 2);
|
|
bytes_read += cfr_read_n(dump->f, &(this_entry->length), 4);
|
|
bytes_read += cfr_read_n(dump->f, &(this_entry->length), 4);
|
|
@@ -144,7 +166,7 @@ BGPDUMP_ENTRY* bgpdump_read_next(BGPDUMP *dump) {
|
|
/* Intel byte ordering stuff ... */
|
|
/* Intel byte ordering stuff ... */
|
|
this_entry->type = ntohs(this_entry->type);
|
|
this_entry->type = ntohs(this_entry->type);
|
|
this_entry->subtype = ntohs(this_entry->subtype);
|
|
this_entry->subtype = ntohs(this_entry->subtype);
|
|
- this_entry->time = ntohl(this_entry->time);
|
|
|
|
|
|
+ this_entry->time = (time_t) ntohl (t);
|
|
this_entry->length = ntohl(this_entry->length);
|
|
this_entry->length = ntohl(this_entry->length);
|
|
|
|
|
|
/* If Extended Header format, then reading the miscroseconds attribute */
|
|
/* If Extended Header format, then reading the miscroseconds attribute */
|
|
@@ -178,7 +200,19 @@ BGPDUMP_ENTRY* bgpdump_read_next(BGPDUMP *dump) {
|
|
dump->parsed++;
|
|
dump->parsed++;
|
|
this_entry->attr=NULL;
|
|
this_entry->attr=NULL;
|
|
|
|
|
|
- buffer = malloc(this_entry->length);
|
|
|
|
|
|
+ if(this_entry->length == 0) {
|
|
|
|
+ err("%s: invalid entry length: 0", __func__);
|
|
|
|
+ free(this_entry);
|
|
|
|
+ dump->eof=1;
|
|
|
|
+ return(NULL);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((buffer = malloc(this_entry->length)) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ free(this_entry);
|
|
|
|
+ dump->eof=1;
|
|
|
|
+ return(NULL);
|
|
|
|
+ }
|
|
bytes_read = cfr_read_n(dump->f, buffer, this_entry->length);
|
|
bytes_read = cfr_read_n(dump->f, buffer, this_entry->length);
|
|
if(bytes_read != this_entry->length) {
|
|
if(bytes_read != this_entry->length) {
|
|
err("bgpdump_read_next: incomplete dump record (%d bytes read, expecting %d)",
|
|
err("bgpdump_read_next: incomplete dump record (%d bytes read, expecting %d)",
|
|
@@ -246,8 +280,16 @@ void bgpdump_free_mem(BGPDUMP_ENTRY *entry) {
|
|
|
|
|
|
switch(entry->type) {
|
|
switch(entry->type) {
|
|
case BGPDUMP_TYPE_ZEBRA_BGP:
|
|
case BGPDUMP_TYPE_ZEBRA_BGP:
|
|
|
|
+ case BGPDUMP_TYPE_ZEBRA_BGP_ET:
|
|
switch(entry->subtype) {
|
|
switch(entry->subtype) {
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
|
|
switch(entry->body.zebra_message.type) {
|
|
switch(entry->body.zebra_message.type) {
|
|
case BGP_MSG_NOTIFY:
|
|
case BGP_MSG_NOTIFY:
|
|
if(entry->body.zebra_message.notify_data)
|
|
if(entry->body.zebra_message.notify_data)
|
|
@@ -262,17 +304,24 @@ void bgpdump_free_mem(BGPDUMP_ENTRY *entry) {
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case BGPDUMP_TYPE_TABLE_DUMP_V2:
|
|
case BGPDUMP_TYPE_TABLE_DUMP_V2:
|
|
- if(entry->subtype == BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST ||
|
|
|
|
- entry->subtype == BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST ){
|
|
|
|
-
|
|
|
|
- BGPDUMP_TABLE_DUMP_V2_PREFIX *e;
|
|
|
|
- e = &entry->body.mrtd_table_dump_v2_prefix;
|
|
|
|
- int i;
|
|
|
|
-
|
|
|
|
- for(i = 0; i < e->entry_count; i++){
|
|
|
|
- bgpdump_free_attr(e->entries[i].attr);
|
|
|
|
- }
|
|
|
|
- free(e->entries);
|
|
|
|
|
|
+ switch(entry->subtype) {
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
|
|
|
|
+ {
|
|
|
|
+ BGPDUMP_TABLE_DUMP_V2_PREFIX *e;
|
|
|
|
+ e = &entry->body.mrtd_table_dump_v2_prefix;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ // Conditional as the entries have already been free'd in this case
|
|
|
|
+ if(!(e->entry_count && entry->dump->table_dump_v2_peer_index_table == NULL)) {
|
|
|
|
+ for(i = 0; i < e->entry_count; i++){
|
|
|
|
+ bgpdump_free_attr(e->entries[i].attr);
|
|
|
|
+ }
|
|
|
|
+ free(e->entries);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -327,30 +376,60 @@ void bgpdump_free_attr(attributes_t *attr){
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Helper function to check if this is an Additional Paths enabled subtype (exported) */
|
|
|
|
+int is_addpath(BGPDUMP_ENTRY *entry) {
|
|
|
|
+ switch(entry->type) {
|
|
|
|
+ case BGPDUMP_TYPE_ZEBRA_BGP:
|
|
|
|
+ case BGPDUMP_TYPE_ZEBRA_BGP_ET:
|
|
|
|
+ switch(entry->subtype) {
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
|
|
|
|
+ return 1;
|
|
|
|
+ default:
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ case BGPDUMP_TYPE_TABLE_DUMP_V2:
|
|
|
|
+ switch(entry->subtype) {
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC_ADDPATH:
|
|
|
|
+ return 1;
|
|
|
|
+ default:
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ default:
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
int process_mrtd_bgp(struct mstream *s, BGPDUMP_ENTRY *entry) {
|
|
int process_mrtd_bgp(struct mstream *s, BGPDUMP_ENTRY *entry) {
|
|
switch(entry->subtype) {
|
|
switch(entry->subtype) {
|
|
case BGPDUMP_SUBTYPE_MRTD_BGP_UPDATE:
|
|
case BGPDUMP_SUBTYPE_MRTD_BGP_UPDATE:
|
|
case BGPDUMP_SUBTYPE_MRTD_BGP_KEEPALIVE:
|
|
case BGPDUMP_SUBTYPE_MRTD_BGP_KEEPALIVE:
|
|
- read_asn(s, &entry->body.mrtd_message.source_as, ASN16_LEN);
|
|
|
|
|
|
+ entry->body.mrtd_message.source_as = read_asn(s, ASN16_LEN);
|
|
entry->body.mrtd_message.source_ip = mstream_get_ipv4(s);
|
|
entry->body.mrtd_message.source_ip = mstream_get_ipv4(s);
|
|
|
|
|
|
- read_asn(s, &entry->body.mrtd_message.destination_as, ASN16_LEN);
|
|
|
|
|
|
+ entry->body.mrtd_message.destination_as = read_asn(s, ASN16_LEN);
|
|
entry->body.mrtd_message.destination_ip = mstream_get_ipv4(s);
|
|
entry->body.mrtd_message.destination_ip = mstream_get_ipv4(s);
|
|
|
|
|
|
mstream_t withdraw_stream = mstream_copy(s, mstream_getw(s, NULL));
|
|
mstream_t withdraw_stream = mstream_copy(s, mstream_getw(s, NULL));
|
|
entry->body.mrtd_message.withdraw_count = read_prefix_list(&withdraw_stream, AFI_IP,
|
|
entry->body.mrtd_message.withdraw_count = read_prefix_list(&withdraw_stream, AFI_IP,
|
|
entry->body.mrtd_message.withdraw,
|
|
entry->body.mrtd_message.withdraw,
|
|
- &entry->body.mrtd_message.incomplete);
|
|
|
|
|
|
+ &entry->body.mrtd_message.incomplete, 0);
|
|
|
|
|
|
- entry->attr = process_attributes(s, ASN16_LEN, &entry->body.mrtd_message.incomplete);
|
|
|
|
|
|
+ if((entry->attr = process_attributes(s, ASN16_LEN, &entry->body.mrtd_message.incomplete, 0)) == NULL)
|
|
|
|
+ return 0;
|
|
|
|
|
|
entry->body.mrtd_message.announce_count = read_prefix_list(s, AFI_IP,
|
|
entry->body.mrtd_message.announce_count = read_prefix_list(s, AFI_IP,
|
|
entry->body.mrtd_message.announce,
|
|
entry->body.mrtd_message.announce,
|
|
- &entry->body.mrtd_message.incomplete);
|
|
|
|
|
|
+ &entry->body.mrtd_message.incomplete, 0);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_MRTD_BGP_STATE_CHANGE:
|
|
case BGPDUMP_SUBTYPE_MRTD_BGP_STATE_CHANGE:
|
|
- read_asn(s, &entry->body.mrtd_state_change.destination_as, ASN16_LEN);
|
|
|
|
|
|
+ entry->body.mrtd_state_change.destination_as = read_asn(s, ASN16_LEN);
|
|
entry->body.mrtd_state_change.destination_ip = mstream_get_ipv4(s);
|
|
entry->body.mrtd_state_change.destination_ip = mstream_get_ipv4(s);
|
|
entry->body.mrtd_state_change.old_state = mstream_getw(s, NULL);
|
|
entry->body.mrtd_state_change.old_state = mstream_getw(s, NULL);
|
|
entry->body.mrtd_state_change.new_state = mstream_getw(s, NULL);
|
|
entry->body.mrtd_state_change.new_state = mstream_getw(s, NULL);
|
|
@@ -412,9 +491,10 @@ int process_mrtd_table_dump(struct mstream *s,BGPDUMP_ENTRY *entry) {
|
|
assert(0); // unreachable
|
|
assert(0); // unreachable
|
|
}
|
|
}
|
|
|
|
|
|
- read_asn(s,&entry->body.mrtd_table_dump.peer_as, asn_len);
|
|
|
|
|
|
+ entry->body.mrtd_table_dump.peer_as = read_asn(s, asn_len);
|
|
|
|
|
|
- entry->attr = process_attributes(s, asn_len, NULL);
|
|
|
|
|
|
+ if((entry->attr = process_attributes(s, asn_len, NULL, 0)) == NULL)
|
|
|
|
+ return 0;
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -427,12 +507,15 @@ int process_mrtd_table_dump_v2(struct mstream *s,BGPDUMP_ENTRY *entry) {
|
|
return process_mrtd_table_dump_v2_peer_index_table(s, entry);
|
|
return process_mrtd_table_dump_v2_peer_index_table(s, entry);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST:
|
|
case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
|
|
return process_mrtd_table_dump_v2_ipv4_unicast(s, entry);
|
|
return process_mrtd_table_dump_v2_ipv4_unicast(s, entry);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST:
|
|
case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
|
|
return process_mrtd_table_dump_v2_ipv6_unicast(s, entry);
|
|
return process_mrtd_table_dump_v2_ipv6_unicast(s, entry);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC:
|
|
case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC:
|
|
|
|
+ case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC_ADDPATH:
|
|
//return process_mrtd_table_dump_v2_generic(s, entry);
|
|
//return process_mrtd_table_dump_v2_generic(s, entry);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -446,19 +529,21 @@ int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY
|
|
uint8_t peertype;
|
|
uint8_t peertype;
|
|
uint16_t view_name_len;
|
|
uint16_t view_name_len;
|
|
|
|
|
|
- if(table_dump_v2_peer_index_table){
|
|
|
|
- if(table_dump_v2_peer_index_table->entries)
|
|
|
|
- free(table_dump_v2_peer_index_table->entries);
|
|
|
|
- free(table_dump_v2_peer_index_table);
|
|
|
|
|
|
+ if(entry->dump->table_dump_v2_peer_index_table) {
|
|
|
|
+ free(entry->dump->table_dump_v2_peer_index_table->entries);
|
|
}
|
|
}
|
|
|
|
+ free(entry->dump->table_dump_v2_peer_index_table);
|
|
|
|
|
|
- table_dump_v2_peer_index_table = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE));
|
|
|
|
- t = table_dump_v2_peer_index_table;
|
|
|
|
|
|
+ if((entry->dump->table_dump_v2_peer_index_table = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE))) == NULL) {
|
|
|
|
+ err("process_mrtd_table_dump_v2_peer_index_table: failed to allocate memory for index table");
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ t = entry->dump->table_dump_v2_peer_index_table;
|
|
t->entries = NULL;
|
|
t->entries = NULL;
|
|
|
|
|
|
- t->local_bgp_id = mstream_get_ipv4(s);
|
|
|
|
|
|
+ t->local_bgp_id = mstream_get_ipv4(s);
|
|
|
|
|
|
- mstream_getw(s,&view_name_len);
|
|
|
|
|
|
+ mstream_getw(s,&view_name_len);
|
|
strcpy(t->view_name, "");
|
|
strcpy(t->view_name, "");
|
|
|
|
|
|
// view_name_len is without trailing \0
|
|
// view_name_len is without trailing \0
|
|
@@ -469,7 +554,7 @@ int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY
|
|
t->view_name[view_name_len] = 0;
|
|
t->view_name[view_name_len] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- mstream_getw(s,&t->peer_count);
|
|
|
|
|
|
+ mstream_getw(s,&t->peer_count);
|
|
|
|
|
|
t->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE_ENTRY) * t->peer_count);
|
|
t->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE_ENTRY) * t->peer_count);
|
|
if(t->entries == NULL){
|
|
if(t->entries == NULL){
|
|
@@ -496,9 +581,9 @@ int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY
|
|
|
|
|
|
|
|
|
|
if(peertype & BGPDUMP_PEERTYPE_TABLE_DUMP_V2_AS4)
|
|
if(peertype & BGPDUMP_PEERTYPE_TABLE_DUMP_V2_AS4)
|
|
- read_asn(s, &t->entries[i].peer_as, 4);
|
|
|
|
|
|
+ t->entries[i].peer_as = read_asn(s, ASN32_LEN);
|
|
else
|
|
else
|
|
- read_asn(s, &t->entries[i].peer_as, 2);
|
|
|
|
|
|
+ t->entries[i].peer_as = read_asn(s, ASN16_LEN);
|
|
|
|
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
@@ -508,6 +593,7 @@ int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY
|
|
int process_mrtd_table_dump_v2_ipv4_unicast(struct mstream *s, BGPDUMP_ENTRY *entry){
|
|
int process_mrtd_table_dump_v2_ipv4_unicast(struct mstream *s, BGPDUMP_ENTRY *entry){
|
|
BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
|
|
BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
|
|
prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
|
|
prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
|
|
|
|
+ int addpath = is_addpath(entry);
|
|
uint16_t i;
|
|
uint16_t i;
|
|
|
|
|
|
prefixdata->afi = AFI_IP;
|
|
prefixdata->afi = AFI_IP;
|
|
@@ -525,15 +611,26 @@ int process_mrtd_table_dump_v2_ipv4_unicast(struct mstream *s, BGPDUMP_ENTRY *en
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if(prefixdata->entry_count && entry->dump->table_dump_v2_peer_index_table == NULL) {
|
|
|
|
+ free(prefixdata->entries);
|
|
|
|
+ err("%s: missing peer index table", __func__);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
for(i=0; i < prefixdata->entry_count; i++){
|
|
for(i=0; i < prefixdata->entry_count; i++){
|
|
BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
|
|
BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
|
|
e = &prefixdata->entries[i];
|
|
e = &prefixdata->entries[i];
|
|
|
|
|
|
mstream_getw(s, &e->peer_index);
|
|
mstream_getw(s, &e->peer_index);
|
|
- e->peer = &table_dump_v2_peer_index_table->entries[e->peer_index];
|
|
|
|
|
|
+ assert(e->peer_index <= entry->dump->table_dump_v2_peer_index_table->peer_count);
|
|
|
|
+ e->peer = &entry->dump->table_dump_v2_peer_index_table->entries[e->peer_index];
|
|
mstream_getl(s, &e->originated_time);
|
|
mstream_getl(s, &e->originated_time);
|
|
|
|
+
|
|
|
|
+ if (addpath)
|
|
|
|
+ mstream_getl(s, &e->path_id);
|
|
|
|
|
|
- e->attr = process_attributes(s, 4, NULL);
|
|
|
|
|
|
+ if((e->attr = process_attributes(s, 4, NULL, is_addpath(entry))) == NULL)
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
@@ -544,6 +641,7 @@ int process_mrtd_table_dump_v2_ipv6_unicast(struct mstream *s, BGPDUMP_ENTRY *en
|
|
#ifdef BGPDUMP_HAVE_IPV6
|
|
#ifdef BGPDUMP_HAVE_IPV6
|
|
BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
|
|
BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
|
|
prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
|
|
prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
|
|
|
|
+ int addpath = is_addpath(entry);
|
|
uint16_t i;
|
|
uint16_t i;
|
|
|
|
|
|
prefixdata->afi = AFI_IP6;
|
|
prefixdata->afi = AFI_IP6;
|
|
@@ -563,15 +661,26 @@ int process_mrtd_table_dump_v2_ipv6_unicast(struct mstream *s, BGPDUMP_ENTRY *en
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if(prefixdata->entry_count && entry->dump->table_dump_v2_peer_index_table == NULL) {
|
|
|
|
+ free(prefixdata->entries);
|
|
|
|
+ err("%s: missing peer index table", __func__);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
for(i=0; i < prefixdata->entry_count; i++){
|
|
for(i=0; i < prefixdata->entry_count; i++){
|
|
BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
|
|
BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
|
|
e = &prefixdata->entries[i];
|
|
e = &prefixdata->entries[i];
|
|
|
|
|
|
mstream_getw(s, &e->peer_index);
|
|
mstream_getw(s, &e->peer_index);
|
|
- e->peer = &table_dump_v2_peer_index_table->entries[e->peer_index];
|
|
|
|
|
|
+ assert(e->peer_index <= entry->dump->table_dump_v2_peer_index_table->peer_count);
|
|
|
|
+ e->peer = &entry->dump->table_dump_v2_peer_index_table->entries[e->peer_index];
|
|
mstream_getl(s, &e->originated_time);
|
|
mstream_getl(s, &e->originated_time);
|
|
|
|
|
|
- e->attr = process_attributes(s, 4, NULL);
|
|
|
|
|
|
+ if (addpath)
|
|
|
|
+ mstream_getl(s, &e->path_id);
|
|
|
|
+
|
|
|
|
+ if((e->attr = process_attributes(s, 4, NULL, is_addpath(entry))) == NULL)
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
#endif
|
|
@@ -586,9 +695,13 @@ int process_zebra_bgp(struct mstream *s,BGPDUMP_ENTRY *entry) {
|
|
return process_zebra_bgp_state_change(s, entry, ASN32_LEN);
|
|
return process_zebra_bgp_state_change(s, entry, ASN32_LEN);
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
|
|
return process_zebra_bgp_message(s, entry, ASN16_LEN);
|
|
return process_zebra_bgp_message(s, entry, ASN16_LEN);
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
|
|
return process_zebra_bgp_message(s, entry, ASN32_LEN);
|
|
return process_zebra_bgp_message(s, entry, ASN32_LEN);
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_ENTRY:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_ENTRY:
|
|
return process_zebra_bgp_entry(s,entry);
|
|
return process_zebra_bgp_entry(s,entry);
|
|
@@ -601,8 +714,8 @@ int process_zebra_bgp(struct mstream *s,BGPDUMP_ENTRY *entry) {
|
|
}
|
|
}
|
|
|
|
|
|
int process_zebra_bgp_state_change(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
|
|
int process_zebra_bgp_state_change(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
|
|
- read_asn(s, &entry->body.zebra_state_change.source_as, asn_len);
|
|
|
|
- read_asn(s, &entry->body.zebra_state_change.destination_as, asn_len);
|
|
|
|
|
|
+ entry->body.zebra_state_change.source_as = read_asn(s, asn_len);
|
|
|
|
+ entry->body.zebra_state_change.destination_as = read_asn(s, asn_len);
|
|
|
|
|
|
/* Work around Zebra dump corruption.
|
|
/* Work around Zebra dump corruption.
|
|
* N.B. I don't see this in quagga 0.96.4 any more. Is it fixed? */
|
|
* N.B. I don't see this in quagga 0.96.4 any more. Is it fixed? */
|
|
@@ -666,14 +779,18 @@ int process_zebra_bgp_message(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t a
|
|
switch(entry->subtype) {
|
|
switch(entry->subtype) {
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
- read_asn(s, &entry->body.zebra_message.destination_as, asn_len);
|
|
|
|
- read_asn(s, &entry->body.zebra_message.source_as, asn_len);
|
|
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
|
|
|
|
+ entry->body.zebra_message.destination_as = read_asn(s, asn_len);
|
|
|
|
+ entry->body.zebra_message.source_as = read_asn(s, asn_len);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
|
|
default:
|
|
default:
|
|
- read_asn(s, &entry->body.zebra_message.source_as, asn_len);
|
|
|
|
- read_asn(s, &entry->body.zebra_message.destination_as, asn_len);
|
|
|
|
|
|
+ entry->body.zebra_message.source_as = read_asn(s, asn_len);
|
|
|
|
+ entry->body.zebra_message.destination_as = read_asn(s, asn_len);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -690,11 +807,15 @@ int process_zebra_bgp_message(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t a
|
|
switch(entry->subtype) {
|
|
switch(entry->subtype) {
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
|
|
entry->body.zebra_message.destination_ip.v4_addr = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.destination_ip.v4_addr = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.source_ip.v4_addr = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.source_ip.v4_addr = mstream_get_ipv4(s);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
|
|
default:
|
|
default:
|
|
entry->body.zebra_message.source_ip.v4_addr = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.source_ip.v4_addr = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.destination_ip.v4_addr = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.destination_ip.v4_addr = mstream_get_ipv4(s);
|
|
@@ -707,11 +828,15 @@ int process_zebra_bgp_message(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t a
|
|
switch(entry->subtype) {
|
|
switch(entry->subtype) {
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
|
|
mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
|
|
mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
|
|
mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
|
|
mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
|
|
break;
|
|
break;
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
|
|
|
|
+ case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
|
|
default:
|
|
default:
|
|
mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
|
|
mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
|
|
mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
|
|
mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
|
|
@@ -789,7 +914,10 @@ int process_zebra_bgp_message_notify(struct mstream *s, BGPDUMP_ENTRY *entry) {
|
|
entry->body.zebra_message.notify_len = entry->body.zebra_message.size - 21;
|
|
entry->body.zebra_message.notify_len = entry->body.zebra_message.size - 21;
|
|
|
|
|
|
if(entry->body.zebra_message.notify_len > 0) {
|
|
if(entry->body.zebra_message.notify_len > 0) {
|
|
- entry->body.zebra_message.notify_data = malloc(entry->body.zebra_message.notify_len);
|
|
|
|
|
|
+ if((entry->body.zebra_message.notify_data = malloc(entry->body.zebra_message.notify_len)) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
mstream_get(s, entry->body.zebra_message.notify_data, entry->body.zebra_message.notify_len);
|
|
mstream_get(s, entry->body.zebra_message.notify_data, entry->body.zebra_message.notify_len);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -798,13 +926,17 @@ int process_zebra_bgp_message_notify(struct mstream *s, BGPDUMP_ENTRY *entry) {
|
|
|
|
|
|
int process_zebra_bgp_message_open(struct mstream *s, BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
|
|
int process_zebra_bgp_message_open(struct mstream *s, BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
|
|
mstream_getc(s, &entry->body.zebra_message.version);
|
|
mstream_getc(s, &entry->body.zebra_message.version);
|
|
- read_asn(s, &entry->body.zebra_message.my_as, asn_len);
|
|
|
|
|
|
+ entry->body.zebra_message.my_as = read_asn(s, asn_len);
|
|
mstream_getw(s, &entry->body.zebra_message.hold_time);
|
|
mstream_getw(s, &entry->body.zebra_message.hold_time);
|
|
entry->body.zebra_message.bgp_id = mstream_get_ipv4(s);
|
|
entry->body.zebra_message.bgp_id = mstream_get_ipv4(s);
|
|
mstream_getc(s, &entry->body.zebra_message.opt_len);
|
|
mstream_getc(s, &entry->body.zebra_message.opt_len);
|
|
|
|
|
|
if(entry->body.zebra_message.opt_len) {
|
|
if(entry->body.zebra_message.opt_len) {
|
|
- entry->body.zebra_message.opt_data = malloc(entry->body.zebra_message.opt_len);
|
|
|
|
|
|
+ if((entry->body.zebra_message.opt_data = malloc(entry->body.zebra_message.opt_len)) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
mstream_get(s, entry->body.zebra_message.opt_data, entry->body.zebra_message.opt_len);
|
|
mstream_get(s, entry->body.zebra_message.opt_data, entry->body.zebra_message.opt_len);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -817,13 +949,16 @@ int process_zebra_bgp_message_update(struct mstream *s, BGPDUMP_ENTRY *entry, u_
|
|
mstream_t withdraw_stream = mstream_copy(s, mstream_getw(s, NULL));
|
|
mstream_t withdraw_stream = mstream_copy(s, mstream_getw(s, NULL));
|
|
entry->body.zebra_message.withdraw_count = read_prefix_list(&withdraw_stream, AFI_IP,
|
|
entry->body.zebra_message.withdraw_count = read_prefix_list(&withdraw_stream, AFI_IP,
|
|
entry->body.zebra_message.withdraw,
|
|
entry->body.zebra_message.withdraw,
|
|
- &entry->body.zebra_message.incomplete);
|
|
|
|
|
|
+ &entry->body.zebra_message.incomplete,
|
|
|
|
+ is_addpath(entry));
|
|
|
|
|
|
- entry->attr = process_attributes(s, asn_len, &entry->body.zebra_message.incomplete);
|
|
|
|
|
|
+ if((entry->attr = process_attributes(s, asn_len, &entry->body.zebra_message.incomplete, is_addpath(entry))) == NULL)
|
|
|
|
+ return 0;
|
|
|
|
|
|
entry->body.zebra_message.announce_count = read_prefix_list(s, AFI_IP,
|
|
entry->body.zebra_message.announce_count = read_prefix_list(s, AFI_IP,
|
|
entry->body.zebra_message.announce,
|
|
entry->body.zebra_message.announce,
|
|
- &entry->body.zebra_message.incomplete);
|
|
|
|
|
|
+ &entry->body.zebra_message.incomplete,
|
|
|
|
+ is_addpath(entry));
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -842,7 +977,15 @@ static attributes_t *attr_init(struct mstream *s, int len) {
|
|
|
|
|
|
attributes_t *attr = malloc(sizeof(struct attr));
|
|
attributes_t *attr = malloc(sizeof(struct attr));
|
|
|
|
|
|
- attr->data=malloc(len);
|
|
|
|
|
|
+ if(attr == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ if((attr->data=malloc(len)) == NULL) {
|
|
|
|
+ free(attr);
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
memcpy(attr->data, &s->start[s->position], len);
|
|
memcpy(attr->data, &s->start[s->position], len);
|
|
|
|
|
|
attr->len = len;
|
|
attr->len = len;
|
|
@@ -861,8 +1004,13 @@ static attributes_t *attr_init(struct mstream *s, int len) {
|
|
attr->aspath = NULL;
|
|
attr->aspath = NULL;
|
|
attr->community = NULL;
|
|
attr->community = NULL;
|
|
attr->transit = NULL;
|
|
attr->transit = NULL;
|
|
- attr->mp_info = calloc(1, sizeof(struct mp_info));;
|
|
|
|
-
|
|
|
|
|
|
+ attr->mp_info = calloc(1, sizeof(struct mp_info));
|
|
|
|
+ if(attr->mp_info == NULL) {
|
|
|
|
+ free(attr->data);
|
|
|
|
+ free(attr);
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
attr->unknown_num = 0;
|
|
attr->unknown_num = 0;
|
|
attr->unknown = NULL;
|
|
attr->unknown = NULL;
|
|
|
|
|
|
@@ -877,8 +1025,11 @@ static attributes_t *attr_init(struct mstream *s, int len) {
|
|
static void process_unknown_attr(struct mstream *s, attributes_t *attr, int flag, int type, int len) {
|
|
static void process_unknown_attr(struct mstream *s, attributes_t *attr, int flag, int type, int len) {
|
|
/* Unknown attribute. Save as is */
|
|
/* Unknown attribute. Save as is */
|
|
attr->unknown_num++;
|
|
attr->unknown_num++;
|
|
- attr->unknown = realloc(attr->unknown, attr->unknown_num * sizeof(struct unknown_attr));
|
|
|
|
-
|
|
|
|
|
|
+ if((attr->unknown = realloc(attr->unknown, attr->unknown_num * sizeof(struct unknown_attr))) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Pointer to the unknown attribute we want to fill in */
|
|
/* Pointer to the unknown attribute we want to fill in */
|
|
struct unknown_attr unknown = {
|
|
struct unknown_attr unknown = {
|
|
.flag = flag,
|
|
.flag = flag,
|
|
@@ -886,13 +1037,16 @@ static void process_unknown_attr(struct mstream *s, attributes_t *attr, int flag
|
|
.len = len,
|
|
.len = len,
|
|
.raw = malloc(len)
|
|
.raw = malloc(len)
|
|
};
|
|
};
|
|
-
|
|
|
|
|
|
+ if(unknown.raw == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
attr->unknown[attr->unknown_num - 1] = unknown;
|
|
attr->unknown[attr->unknown_num - 1] = unknown;
|
|
|
|
|
|
mstream_get(s, unknown.raw, len);
|
|
mstream_get(s, unknown.raw, len);
|
|
}
|
|
}
|
|
|
|
|
|
-static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u_int8_t asn_len, struct zebra_incomplete *incomplete) {
|
|
|
|
|
|
+static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u_int8_t asn_len, struct zebra_incomplete *incomplete, int is_addp) {
|
|
int flag = mstream_getc(outer_stream, NULL);
|
|
int flag = mstream_getc(outer_stream, NULL);
|
|
int type = mstream_getc(outer_stream, NULL);
|
|
int type = mstream_getc(outer_stream, NULL);
|
|
int len;
|
|
int len;
|
|
@@ -916,10 +1070,10 @@ static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u
|
|
|
|
|
|
switch(type) {
|
|
switch(type) {
|
|
case BGP_ATTR_MP_REACH_NLRI:
|
|
case BGP_ATTR_MP_REACH_NLRI:
|
|
- process_mp_announce(s, attr->mp_info, incomplete);
|
|
|
|
|
|
+ process_mp_announce(s, attr->mp_info, incomplete, is_addp);
|
|
break;
|
|
break;
|
|
case BGP_ATTR_MP_UNREACH_NLRI:
|
|
case BGP_ATTR_MP_UNREACH_NLRI:
|
|
- process_mp_withdraw(s, attr->mp_info, incomplete);
|
|
|
|
|
|
+ process_mp_withdraw(s, attr->mp_info, incomplete, is_addp);
|
|
break;
|
|
break;
|
|
case BGP_ATTR_ORIGIN:
|
|
case BGP_ATTR_ORIGIN:
|
|
assert(attr->origin == -1);
|
|
assert(attr->origin == -1);
|
|
@@ -947,14 +1101,22 @@ static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u
|
|
break;
|
|
break;
|
|
case BGP_ATTR_AGGREGATOR:
|
|
case BGP_ATTR_AGGREGATOR:
|
|
assert(-1 == attr->new_aggregator_as);
|
|
assert(-1 == attr->new_aggregator_as);
|
|
- read_asn(s, &attr->aggregator_as, asn_len);
|
|
|
|
|
|
+ attr->aggregator_as = read_asn(s, asn_len);
|
|
attr->aggregator_addr = mstream_get_ipv4(s);
|
|
attr->aggregator_addr = mstream_get_ipv4(s);
|
|
break;
|
|
break;
|
|
case BGP_ATTR_COMMUNITIES:
|
|
case BGP_ATTR_COMMUNITIES:
|
|
assert(! attr->community);
|
|
assert(! attr->community);
|
|
- attr->community = malloc(sizeof(struct community));
|
|
|
|
|
|
+ if((attr->community = malloc(sizeof(struct community))) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
|
|
+
|
|
attr->community->size = len / 4;
|
|
attr->community->size = len / 4;
|
|
- attr->community->val = malloc(len);
|
|
|
|
|
|
+ if((attr->community->val = malloc(len)) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
|
|
+
|
|
mstream_get(s,attr->community->val,len);
|
|
mstream_get(s,attr->community->val,len);
|
|
attr->community->str = NULL;
|
|
attr->community->str = NULL;
|
|
process_attr_community_string(attr->community);
|
|
process_attr_community_string(attr->community);
|
|
@@ -969,7 +1131,7 @@ static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u
|
|
break;
|
|
break;
|
|
case BGP_ATTR_NEW_AGGREGATOR:
|
|
case BGP_ATTR_NEW_AGGREGATOR:
|
|
assert(-1 == attr->new_aggregator_as);
|
|
assert(-1 == attr->new_aggregator_as);
|
|
- read_asn(s, &attr->new_aggregator_as, ASN32_LEN);
|
|
|
|
|
|
+ attr->new_aggregator_as = read_asn(s, ASN32_LEN);
|
|
attr->new_aggregator_addr = mstream_get_ipv4(s);
|
|
attr->new_aggregator_addr = mstream_get_ipv4(s);
|
|
break;
|
|
break;
|
|
case BGP_ATTR_ORIGINATOR_ID:
|
|
case BGP_ATTR_ORIGINATOR_ID:
|
|
@@ -978,9 +1140,15 @@ static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u
|
|
break;
|
|
break;
|
|
case BGP_ATTR_CLUSTER_LIST:
|
|
case BGP_ATTR_CLUSTER_LIST:
|
|
assert(! attr->cluster);
|
|
assert(! attr->cluster);
|
|
- attr->cluster = malloc(sizeof(struct cluster_list));
|
|
|
|
|
|
+ if((attr->cluster= malloc(sizeof(struct cluster_list))) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
attr->cluster->length = len/4;
|
|
attr->cluster->length = len/4;
|
|
- attr->cluster->list = malloc((attr->cluster->length) * sizeof(struct in_addr));
|
|
|
|
|
|
+ if((attr->cluster->list = calloc((attr->cluster->length), sizeof(struct in_addr))) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
|
|
|
|
int i; // cluster index
|
|
int i; // cluster index
|
|
for (i = 0; i < attr->cluster->length; i++)
|
|
for (i = 0; i < attr->cluster->length; i++)
|
|
@@ -991,17 +1159,20 @@ static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-attributes_t *process_attributes(struct mstream *s, u_int8_t asn_len, struct zebra_incomplete *incomplete) {
|
|
|
|
|
|
+attributes_t *process_attributes(struct mstream *s, u_int8_t asn_len, struct zebra_incomplete *incomplete, int is_addp) {
|
|
int total = mstream_getw(s, NULL);
|
|
int total = mstream_getw(s, NULL);
|
|
|
|
|
|
attributes_t *attr = attr_init(s, total);
|
|
attributes_t *attr = attr_init(s, total);
|
|
|
|
+ if(attr == NULL)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
mstream_t copy = mstream_copy(s, total);
|
|
mstream_t copy = mstream_copy(s, total);
|
|
|
|
|
|
if(mstream_can_read(©) != total)
|
|
if(mstream_can_read(©) != total)
|
|
warn("entry is truncated: expected=%u remaining=%u", total, mstream_can_read(©));
|
|
warn("entry is truncated: expected=%u remaining=%u", total, mstream_can_read(©));
|
|
|
|
|
|
while(mstream_can_read(©))
|
|
while(mstream_can_read(©))
|
|
- process_one_attr(©, attr, asn_len, incomplete);
|
|
|
|
|
|
+ process_one_attr(©, attr, asn_len, incomplete, is_addp);
|
|
|
|
|
|
// Once all attributes have been read, take care of ASN32 transition
|
|
// Once all attributes have been read, take care of ASN32 transition
|
|
process_asn32_trans(attr, asn_len);
|
|
process_asn32_trans(attr, asn_len);
|
|
@@ -1016,11 +1187,16 @@ struct aspath *create_aspath(u_int16_t len, u_int8_t asn_len) {
|
|
aspath->length = len;
|
|
aspath->length = len;
|
|
aspath->count = 0;
|
|
aspath->count = 0;
|
|
aspath->str = NULL;
|
|
aspath->str = NULL;
|
|
- if(len > 0)
|
|
|
|
- aspath->data = malloc(len);
|
|
|
|
- else
|
|
|
|
|
|
+ if(len > 0) {
|
|
|
|
+ if((aspath->data = malloc(len)) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ free(aspath);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ } else
|
|
aspath->data = NULL;
|
|
aspath->data = NULL;
|
|
- }
|
|
|
|
|
|
+ } else
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
return aspath;
|
|
return aspath;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1033,13 +1209,17 @@ void aspath_error(struct aspath *as) {
|
|
}
|
|
}
|
|
|
|
|
|
as->str = malloc(strlen(ASPATH_STR_ERROR) + 1);
|
|
as->str = malloc(strlen(ASPATH_STR_ERROR) + 1);
|
|
- strcpy(as->str, ASPATH_STR_ERROR);
|
|
|
|
|
|
+ if (as->str != NULL)
|
|
|
|
+ strcpy(as->str, ASPATH_STR_ERROR);
|
|
}
|
|
}
|
|
|
|
|
|
void process_attr_aspath_string(struct aspath *as) {
|
|
void process_attr_aspath_string(struct aspath *as) {
|
|
const int MAX_ASPATH_LEN = 8000;
|
|
const int MAX_ASPATH_LEN = 8000;
|
|
- as->str = malloc(MAX_ASPATH_LEN);
|
|
|
|
-
|
|
|
|
|
|
+ if((as->str = malloc(MAX_ASPATH_LEN)) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Set default values */
|
|
/* Set default values */
|
|
int space = 0;
|
|
int space = 0;
|
|
u_char type = AS_SEQUENCE;
|
|
u_char type = AS_SEQUENCE;
|
|
@@ -1206,46 +1386,55 @@ void process_attr_community_string(struct community *com) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- com->str = malloc(strlen(buf)+1);
|
|
|
|
- strcpy(com->str, buf);
|
|
|
|
|
|
+ if((com->str = malloc(strlen(buf)+1)) != NULL) {
|
|
|
|
+ strcpy(com->str, buf);
|
|
|
|
+ } else {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-static struct mp_nlri *get_nexthop(struct mstream *s, u_int16_t afi) {
|
|
|
|
|
|
+static struct mp_nlri *get_nexthop(struct mstream *s) {
|
|
struct mp_nlri *nlri = calloc(1, sizeof(struct mp_nlri));
|
|
struct mp_nlri *nlri = calloc(1, sizeof(struct mp_nlri));
|
|
|
|
|
|
|
|
+ if(nlri == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
nlri->nexthop_len = mstream_getc(s, NULL);
|
|
nlri->nexthop_len = mstream_getc(s, NULL);
|
|
|
|
|
|
// sometimes nexthop_len is 0 - not sure what this means (see IS-626)
|
|
// sometimes nexthop_len is 0 - not sure what this means (see IS-626)
|
|
// if(mp_nlri->nexthop_len == 0)
|
|
// if(mp_nlri->nexthop_len == 0)
|
|
// return len;
|
|
// return len;
|
|
|
|
|
|
- if(afi == AFI_IP) {
|
|
|
|
- assert(nlri->nexthop_len == 4);
|
|
|
|
- nlri->nexthop.v4_addr = mstream_get_ipv4(s);
|
|
|
|
- return nlri;
|
|
|
|
- }
|
|
|
|
|
|
+ // the AFI is irrelevant to the nexthop, since RFC5549
|
|
|
|
+ // so this code now just checks for an expected length:
|
|
|
|
+ // 4 = IPv4
|
|
|
|
+ // 16 = IPv6
|
|
|
|
+ // 32 = IPv6 + link-local
|
|
|
|
|
|
-#ifdef BGPDUMP_HAVE_IPV6
|
|
|
|
- assert(afi == AFI_IP6);
|
|
|
|
- mstream_get(s, &nlri->nexthop.v6_addr, 16);
|
|
|
|
- if(nlri->nexthop_len == 32) {
|
|
|
|
- /* Is there also a link-local address? */
|
|
|
|
|
|
+ if(nlri->nexthop_len == 4) {
|
|
|
|
+ nlri->nexthop.v4_addr = mstream_get_ipv4(s);
|
|
|
|
+ } else if(nlri->nexthop_len == 16) {
|
|
|
|
+ mstream_get(s, &nlri->nexthop.v6_addr, 16);
|
|
|
|
+ } else if(nlri->nexthop_len == 32) {
|
|
|
|
+ mstream_get(s, &nlri->nexthop.v6_addr, 16);
|
|
mstream_get(s, &nlri->nexthop_local.v6_addr.s6_addr, 16);
|
|
mstream_get(s, &nlri->nexthop_local.v6_addr.s6_addr, 16);
|
|
- } else if(nlri->nexthop_len != 16) {
|
|
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
warn("process_mp_announce: unknown MP nexthop length %d", nlri->nexthop_len);
|
|
warn("process_mp_announce: unknown MP nexthop length %d", nlri->nexthop_len);
|
|
}
|
|
}
|
|
-#endif
|
|
|
|
return nlri;
|
|
return nlri;
|
|
}
|
|
}
|
|
|
|
|
|
-void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete) {
|
|
|
|
|
|
+void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp) {
|
|
u_int16_t afi;
|
|
u_int16_t afi;
|
|
u_int8_t safi;
|
|
u_int8_t safi;
|
|
|
|
|
|
// look for MRT abbreviated MP_NLRI packets
|
|
// look for MRT abbreviated MP_NLRI packets
|
|
if(s->start[s->position] != 0) {
|
|
if(s->start[s->position] != 0) {
|
|
assert(info->announce[AFI_IP6][SAFI_UNICAST] == NULL);
|
|
assert(info->announce[AFI_IP6][SAFI_UNICAST] == NULL);
|
|
- info->announce[AFI_IP6][SAFI_UNICAST] = get_nexthop(s, AFI_IP6);
|
|
|
|
|
|
+ info->announce[AFI_IP6][SAFI_UNICAST] = get_nexthop(s);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1262,7 +1451,7 @@ void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_i
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- info->announce[afi][safi] = get_nexthop(s, afi);
|
|
|
|
|
|
+ info->announce[afi][safi] = get_nexthop(s);
|
|
|
|
|
|
// SNPA is defunct and num_snpa should always be 0
|
|
// SNPA is defunct and num_snpa should always be 0
|
|
u_int8_t num_snpa;
|
|
u_int8_t num_snpa;
|
|
@@ -1272,10 +1461,10 @@ void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_i
|
|
mstream_get(s, NULL, mstream_getc(s, NULL));
|
|
mstream_get(s, NULL, mstream_getc(s, NULL));
|
|
}
|
|
}
|
|
|
|
|
|
- info->announce[afi][safi]->prefix_count = read_prefix_list(s, afi, info->announce[afi][safi]->nlri, incomplete);
|
|
|
|
|
|
+ info->announce[afi][safi]->prefix_count = read_prefix_list(s, afi, info->announce[afi][safi]->nlri, incomplete, is_addp);
|
|
}
|
|
}
|
|
|
|
|
|
-void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete) {
|
|
|
|
|
|
+void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp) {
|
|
u_int16_t afi;
|
|
u_int16_t afi;
|
|
u_int8_t safi;
|
|
u_int8_t safi;
|
|
struct mp_nlri *mp_nlri;
|
|
struct mp_nlri *mp_nlri;
|
|
@@ -1296,17 +1485,27 @@ void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_i
|
|
}
|
|
}
|
|
|
|
|
|
/* Allocate structure */
|
|
/* Allocate structure */
|
|
- mp_nlri = malloc(sizeof(struct mp_nlri));
|
|
|
|
|
|
+ if((mp_nlri = malloc(sizeof(struct mp_nlri))) == NULL) {
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ exit(1); /* XXX */
|
|
|
|
+ }
|
|
memset(mp_nlri, 0, sizeof(struct mp_nlri));
|
|
memset(mp_nlri, 0, sizeof(struct mp_nlri));
|
|
info->withdraw[afi][safi] = mp_nlri;
|
|
info->withdraw[afi][safi] = mp_nlri;
|
|
|
|
|
|
- mp_nlri->prefix_count = read_prefix_list(s, afi, mp_nlri->nlri, incomplete);
|
|
|
|
|
|
+ mp_nlri->prefix_count = read_prefix_list(s, afi, mp_nlri->nlri, incomplete, is_addp);
|
|
}
|
|
}
|
|
|
|
|
|
-static int read_prefix_list(struct mstream *s, u_int16_t afi, struct prefix *prefixes, struct zebra_incomplete *incomplete) {
|
|
|
|
|
|
+static int read_prefix_list(struct mstream *s, u_int16_t afi, struct prefix *prefixes, struct zebra_incomplete *incomplete, int is_addp) {
|
|
int count = 0;
|
|
int count = 0;
|
|
|
|
|
|
while(mstream_can_read(s)) {
|
|
while(mstream_can_read(s)) {
|
|
|
|
+
|
|
|
|
+ /* If this is an Additional Paths enabled NLRI, then there is a
|
|
|
|
+ * 4 octet identifier preceeding each prefix entry */
|
|
|
|
+ pathid_t path_id = 0;
|
|
|
|
+ if (is_addp)
|
|
|
|
+ path_id = mstream_getl(s, NULL);
|
|
|
|
+
|
|
u_int8_t p_len = mstream_getc(s,NULL); // length in bits
|
|
u_int8_t p_len = mstream_getc(s,NULL); // length in bits
|
|
u_int8_t p_bytes = (p_len + 7) / 8;
|
|
u_int8_t p_bytes = (p_len + 7) / 8;
|
|
|
|
|
|
@@ -1319,7 +1518,8 @@ static int read_prefix_list(struct mstream *s, u_int16_t afi, struct prefix *pre
|
|
incomplete->afi = afi;
|
|
incomplete->afi = afi;
|
|
incomplete->orig_len = p_len;
|
|
incomplete->orig_len = p_len;
|
|
incomplete->prefix = (struct prefix) {
|
|
incomplete->prefix = (struct prefix) {
|
|
- .len = mstream_can_read(s) * 8
|
|
|
|
|
|
+ .len = mstream_can_read(s) * 8,
|
|
|
|
+ .path_id = path_id
|
|
};
|
|
};
|
|
mstream_get(s, &incomplete->prefix.address, p_bytes);
|
|
mstream_get(s, &incomplete->prefix.address, p_bytes);
|
|
break;
|
|
break;
|
|
@@ -1330,7 +1530,7 @@ static int read_prefix_list(struct mstream *s, u_int16_t afi, struct prefix *pre
|
|
if(count++ > MAX_PREFIXES)
|
|
if(count++ > MAX_PREFIXES)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- *prefix = (struct prefix) { .len = p_len };
|
|
|
|
|
|
+ *prefix = (struct prefix) { .len = p_len, .path_id = path_id };
|
|
mstream_get(s, &prefix->address, p_bytes);
|
|
mstream_get(s, &prefix->address, p_bytes);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1342,18 +1542,13 @@ static int read_prefix_list(struct mstream *s, u_int16_t afi, struct prefix *pre
|
|
return count;
|
|
return count;
|
|
}
|
|
}
|
|
|
|
|
|
-static as_t read_asn(struct mstream *s, as_t *asn, u_int8_t len) {
|
|
|
|
- u_int16_t asn16;
|
|
|
|
-
|
|
|
|
- assert(len == sizeof(u_int32_t) || len == sizeof(u_int16_t));
|
|
|
|
|
|
+static as_t read_asn(struct mstream *s, u_int8_t len) {
|
|
|
|
+ assert(len == ASN32_LEN || len == ASN16_LEN);
|
|
switch(len) {
|
|
switch(len) {
|
|
- case sizeof(u_int32_t):
|
|
|
|
- return mstream_getl(s, asn);
|
|
|
|
- case sizeof(u_int16_t):
|
|
|
|
- mstream_getw(s, &asn16);
|
|
|
|
- if(asn)
|
|
|
|
- *asn = asn16;
|
|
|
|
- return asn16;
|
|
|
|
|
|
+ case ASN32_LEN:
|
|
|
|
+ return mstream_getl(s, NULL);
|
|
|
|
+ case ASN16_LEN:
|
|
|
|
+ return mstream_getw(s, NULL);
|
|
default:
|
|
default:
|
|
/* Not reached. Avoid compiler warning */
|
|
/* Not reached. Avoid compiler warning */
|
|
return 0;
|
|
return 0;
|
|
@@ -1421,7 +1616,10 @@ void process_asn32_trans(attributes_t *attr, u_int8_t asn_len) {
|
|
}
|
|
}
|
|
|
|
|
|
struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath) {
|
|
struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath) {
|
|
|
|
+ void *tmp;
|
|
struct aspath *mergedpath = create_aspath(0, ASN32_LEN);
|
|
struct aspath *mergedpath = create_aspath(0, ASN32_LEN);
|
|
|
|
+ if(mergedpath == NULL)
|
|
|
|
+ return NULL;
|
|
struct assegment *segment, *mergedsegment;
|
|
struct assegment *segment, *mergedsegment;
|
|
int newlen;
|
|
int newlen;
|
|
|
|
|
|
@@ -1430,7 +1628,14 @@ struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath) {
|
|
while(mergedpath->count < path->count - newpath->count) {
|
|
while(mergedpath->count < path->count - newpath->count) {
|
|
/* Make room */
|
|
/* Make room */
|
|
newlen = mergedpath->length + sizeof(struct assegment) + segment->length * ASN32_LEN;
|
|
newlen = mergedpath->length + sizeof(struct assegment) + segment->length * ASN32_LEN;
|
|
- mergedpath->data = realloc(mergedpath->data, newlen);
|
|
|
|
|
|
+ tmp = realloc(mergedpath->data, newlen);
|
|
|
|
+ if(tmp == NULL) {
|
|
|
|
+ free(mergedpath->data);
|
|
|
|
+ free(mergedpath);
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ mergedpath->data = tmp;
|
|
|
|
|
|
/* Create a new AS-path segment */
|
|
/* Create a new AS-path segment */
|
|
mergedsegment = (struct assegment *) (mergedpath->data + mergedpath->length);
|
|
mergedsegment = (struct assegment *) (mergedpath->data + mergedpath->length);
|
|
@@ -1455,7 +1660,14 @@ struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath) {
|
|
}
|
|
}
|
|
|
|
|
|
/* Append NEW_AS_PATH to merged path */
|
|
/* Append NEW_AS_PATH to merged path */
|
|
- mergedpath->data = realloc(mergedpath->data, mergedpath->length + newpath->length);
|
|
|
|
|
|
+ tmp = realloc(mergedpath->data, mergedpath->length + newpath->length);
|
|
|
|
+ if(tmp == NULL) {
|
|
|
|
+ free(mergedpath->data);
|
|
|
|
+ free(mergedpath);
|
|
|
|
+ err("%s: out of memory", __func__);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ mergedpath->data = tmp;
|
|
memcpy(mergedpath->data + mergedpath->length, newpath->data, newpath->length);
|
|
memcpy(mergedpath->data + mergedpath->length, newpath->data, newpath->length);
|
|
mergedpath->length += newpath->length;
|
|
mergedpath->length += newpath->length;
|
|
|
|
|
|
@@ -1482,3 +1694,4 @@ size_t strlcat(char *dst, const char *src, size_t size) {
|
|
return (strlen(dst));
|
|
return (strlen(dst));
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
+
|