1 /*
2  Copyright (c) 2007 - 2010 RIPE NCC - All Rights Reserved
3 
4  Permission to use, copy, modify, and distribute this software and its
5  documentation for any purpose and without fee is hereby granted, provided
6  that the above copyright notice appear in all copies and that both that
7  copyright notice and this permission notice appear in supporting
8  documentation, and that the name of the author not be used in advertising or
9  publicity pertaining to distribution of the software without specific,
10  written prior permission.
11 
12  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
14  AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
15  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
16  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 
19 Parts of this code have been engineered after analiyzing GNU Zebra's
20 source code and therefore might contain declarations/code from GNU
21 Zebra, Copyright (C) 1999 Kunihiro Ishiguro. Zebra is a free routing
22 software, distributed under the GNU General Public License. A copy of
23 this license is included with libbgpdump.
24 */
25 
26 #include "bgpdump-config.h"
27 #include "cfile_tools.h"
28 #include "bgpdump_lib.h"
29 #include "bgpdump_mstream.h"
30 #include "util.h"
31 
32 #include <sys/stat.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <stdbool.h>
36 
37 #include <netinet/in.h>
38 #include <sys/socket.h>
39 #include <arpa/inet.h>
40 
41 #include <zlib.h>
42 #include <assert.h>
43 
44 void	  bgpdump_free_attr(attributes_t *attr);
45 static    BGPDUMP_ENTRY* bgpdump_entry_create(BGPDUMP *dump);
46 static    int process_mrtd_bgp(struct mstream *s, BGPDUMP_ENTRY *entry);
47 static    int process_mrtd_table_dump(struct mstream *s,BGPDUMP_ENTRY *entry);
48 static    int process_mrtd_table_dump_v2(struct mstream *s,BGPDUMP_ENTRY *entry);
49 static    int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY *entry);
50 static    int process_mrtd_table_dump_v2_ipv4_unicast(struct mstream *s,BGPDUMP_ENTRY *entry);
51 static    int process_mrtd_table_dump_v2_ipv6_unicast(struct mstream *s,BGPDUMP_ENTRY *entry);
52 static    int process_zebra_bgp(struct mstream *s,BGPDUMP_ENTRY *entry);
53 static    int process_zebra_bgp_state_change(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len);
54 
55 static    int process_zebra_bgp_message(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len);
56 static    int process_zebra_bgp_message_update(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len);
57 static    int process_zebra_bgp_message_open(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len);
58 static    int process_zebra_bgp_message_notify(struct mstream *s,BGPDUMP_ENTRY *entry);
59 
60 static    int process_zebra_bgp_entry(struct mstream *s,BGPDUMP_ENTRY *entry);
61 static    int process_zebra_bgp_snapshot(struct mstream *s,BGPDUMP_ENTRY *entry);
62 
63 static    attributes_t *process_attributes(struct mstream *s, u_int8_t asn_len, struct zebra_incomplete *incomplete, int is_addp);
64 static    void process_attr_aspath_string(struct aspath *as);
65 static    char aspath_delimiter_char (u_char type, u_char which);
66 static    void process_attr_community_string(struct community *com);
67 static    void process_attr_lcommunity_string(struct lcommunity *lcom);
68 
69 static    void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp);
70 static    void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp);
71 static    int read_prefix_list(struct mstream *s, u_int16_t af, struct prefix *prefixes, struct zebra_incomplete *incomplete, int is_addp);
72 
73 static    as_t read_asn(struct mstream *s, u_int8_t len);
74 static    struct aspath *create_aspath(u_int16_t len, u_int8_t asn_len);
75 static    void aspath_error(struct aspath *as);
76 static    int check_new_aspath(struct aspath *aspath);
77 static    void process_asn32_trans(attributes_t *attr, u_int8_t asn_len);
78 static    struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath);
79 static    void asn32_expand_16_to_32(char *dst, char *src, int len);
80 
81 #if defined(linux)
82 static    size_t strlcat(char *dst, const char *src, size_t size);
83 #endif
84 
bgpdump_version(void)85 char *bgpdump_version(void) {
86     return PACKAGE_VERSION;
87 }
88 
89 
bgpdump_open_dump(const char * filename)90 BGPDUMP *bgpdump_open_dump(const char *filename) {
91 
92     CFRFILE *f = cfr_open(filename);
93     if(! f) {
94         perror("can't open dumpfile");
95         return NULL;
96     }
97     BGPDUMP *this_dump = malloc(sizeof(BGPDUMP));
98     if (this_dump == NULL) {
99         perror("malloc");
100         return NULL;
101     }
102     strcpy(this_dump->filename, "[STDIN]");
103     if(filename && strcmp(filename, "-")) {
104         if (strlen(filename) >= BGPDUMP_MAX_FILE_LEN - 1) {
105             fprintf (stderr, "File name %s is too long.\n", filename);
106             exit(1);
107         }
108 	strcpy(this_dump->filename, filename);
109     }
110 
111     this_dump->f = f;
112     this_dump->eof=0;
113     this_dump->parsed = 0;
114     this_dump->parsed_ok = 0;
115     // peer index table shared among entries
116     this_dump->table_dump_v2_peer_index_table = NULL;
117 
118     return this_dump;
119 }
120 
bgpdump_close_dump(BGPDUMP * dump)121 void bgpdump_close_dump(BGPDUMP *dump) {
122 
123     if(dump == NULL) {
124         return;
125     }
126 
127     if(dump->table_dump_v2_peer_index_table){
128         free(dump->table_dump_v2_peer_index_table->entries);
129     }
130     free(dump->table_dump_v2_peer_index_table);
131 	cfr_close(dump->f);
132     free(dump);
133 }
134 
bgpdump_entry_create(BGPDUMP * dump)135 BGPDUMP_ENTRY* bgpdump_entry_create(BGPDUMP *dump){
136     BGPDUMP_ENTRY *this_entry = malloc(sizeof(BGPDUMP_ENTRY));
137     if(this_entry == NULL) {
138         err("%s: out of memory", __func__);
139         return NULL;
140     }
141     memset(this_entry, 0, sizeof(BGPDUMP_ENTRY));
142     this_entry->dump = dump;
143     return this_entry;
144 }
145 
bgpdump_read_next(BGPDUMP * dump)146 BGPDUMP_ENTRY*	bgpdump_read_next(BGPDUMP *dump) {
147     assert(dump);
148 
149     struct mstream s;
150     u_char *buffer;
151     int ok=0;
152     u_int32_t bytes_read, t;
153 
154     BGPDUMP_ENTRY *this_entry = bgpdump_entry_create(dump);
155     if(this_entry == NULL) {
156         err("%s: out of memmory", __func__);
157         dump->eof = 1;
158         return(NULL);
159     }
160 
161     bytes_read = cfr_read_n(dump->f, &t, 4);
162     bytes_read += cfr_read_n(dump->f, &(this_entry->type), 2);
163     bytes_read += cfr_read_n(dump->f, &(this_entry->subtype), 2);
164     bytes_read += cfr_read_n(dump->f, &(this_entry->length), 4);
165 
166     if (bytes_read == 12) {
167         /* Intel byte ordering stuff ... */
168         this_entry->type = ntohs(this_entry->type);
169         this_entry->subtype = ntohs(this_entry->subtype);
170         this_entry->time = (time_t) ntohl (t);
171         this_entry->length = ntohl(this_entry->length);
172 
173         /* If Extended Header format, then reading the miscroseconds attribute */
174         if (this_entry->type == BGPDUMP_TYPE_ZEBRA_BGP_ET) {
175             bytes_read += cfr_read_n(dump->f, &(this_entry->ms), 4);
176             if (bytes_read == 16) {
177                 this_entry->ms = ntohl(this_entry->ms);
178                 /* "The Microsecond Timestamp is included in the computation of
179                  * the Length field value." (RFC6396 2011) */
180                 this_entry->length -= 4;
181                 ok = 1;
182             }
183         } else {
184             this_entry->ms = 0;
185             ok = 1;
186         }
187     }
188 
189     if (!ok) {
190         if(bytes_read > 0) {
191             /* Malformed record */
192             err("bgpdump_read_next: incomplete MRT header (%d bytes read, expecting 12 or 16)",
193                 bytes_read);
194         }
195         /* Nothing more to read, quit */
196         free(this_entry);
197         dump->eof = 1;
198         return(NULL);
199     }
200 
201     dump->parsed++;
202     this_entry->attr=NULL;
203 
204     if(this_entry->length == 0) {
205         err("%s: invalid entry length: 0", __func__);
206 	free(this_entry);
207 	dump->eof=1;
208 	return(NULL);
209     }
210 
211     if ((buffer = malloc(this_entry->length)) == NULL) {
212 	err("%s: out of memory", __func__);
213 	free(this_entry);
214 	dump->eof=1;
215 	return(NULL);
216     }
217     bytes_read = cfr_read_n(dump->f, buffer, this_entry->length);
218     if(bytes_read != this_entry->length) {
219 	err("bgpdump_read_next: incomplete dump record (%d bytes read, expecting %d)",
220 	       bytes_read, this_entry->length);
221 	free(this_entry);
222 	free(buffer);
223 	dump->eof=1;
224 	return(NULL);
225     }
226 
227 
228     ok=0;
229     mstream_init(&s,buffer,this_entry->length);
230 
231     switch(this_entry->type) {
232 	case BGPDUMP_TYPE_MRTD_BGP:
233 		ok = process_mrtd_bgp(&s,this_entry);
234 		break;
235 	case BGPDUMP_TYPE_MRTD_TABLE_DUMP:
236 		ok = process_mrtd_table_dump(&s,this_entry);
237 		break;
238 	case BGPDUMP_TYPE_ZEBRA_BGP:
239     case BGPDUMP_TYPE_ZEBRA_BGP_ET:
240 		ok = process_zebra_bgp(&s,this_entry);
241 		break;
242 	case BGPDUMP_TYPE_TABLE_DUMP_V2:
243 		ok = process_mrtd_table_dump_v2(&s,this_entry);
244 		break;
245     }
246 
247     free(buffer);
248     if(ok) {
249 	dump->parsed_ok++;
250     } else {
251 	bgpdump_free_mem(this_entry);
252 	return NULL;
253     }
254     return this_entry;
255 }
256 
bgpdump_free_mp_info(struct mp_info * info)257 static void bgpdump_free_mp_info(struct mp_info *info) {
258     u_int16_t afi;
259     u_int8_t safi;
260 
261     for(afi = 1; afi <= BGPDUMP_MAX_AFI; afi++) {
262 	for(safi = 1; safi <= BGPDUMP_MAX_SAFI; safi++) {
263 	    if(info->announce[afi][safi])
264 		free(info->announce[afi][safi]);
265 		info->announce[afi][safi] = NULL;
266 	    if(info->withdraw[afi][safi]) {
267 		free(info->withdraw[afi][safi]);
268 		info->withdraw[afi][safi] = NULL;
269 	    }
270 	}
271     }
272 
273 	free(info);
274 }
275 
bgpdump_free_mem(BGPDUMP_ENTRY * entry)276 void bgpdump_free_mem(BGPDUMP_ENTRY *entry) {
277 
278     if(entry!=NULL) {
279 
280 	bgpdump_free_attr(entry->attr);
281 
282 	switch(entry->type) {
283 	    case BGPDUMP_TYPE_ZEBRA_BGP:
284 	    case BGPDUMP_TYPE_ZEBRA_BGP_ET:
285 		switch(entry->subtype) {
286 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
287 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
288 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
289 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
290 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
291 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
292 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
293 		    case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
294 			switch(entry->body.zebra_message.type) {
295 			    case BGP_MSG_NOTIFY:
296 				if(entry->body.zebra_message.notify_data)
297 				    free(entry->body.zebra_message.notify_data);
298 				break;
299 			    case BGP_MSG_OPEN:
300 				if(entry->body.zebra_message.opt_data)
301 				    free(entry->body.zebra_message.opt_data);
302 				break;
303 			}
304 			break;
305 		}
306 		break;
307 	    case BGPDUMP_TYPE_TABLE_DUMP_V2:
308         switch(entry->subtype) {
309             case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST:
310             case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST:
311             case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
312             case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
313             {
314                 BGPDUMP_TABLE_DUMP_V2_PREFIX *e;
315                 e = &entry->body.mrtd_table_dump_v2_prefix;
316                 int i;
317 
318                 // Conditional as the entries have already been free'd in this case
319                 if(!(e->entry_count && entry->dump->table_dump_v2_peer_index_table == NULL)) {
320                     for(i = 0; i < e->entry_count; i++){
321                         bgpdump_free_attr(e->entries[i].attr);
322                     }
323                     free(e->entries);
324                 }
325             }
326 		}
327 		break;
328 	}
329 
330 	free(entry);
331     }
332 }
333 
bgpdump_free_attr(attributes_t * attr)334 void bgpdump_free_attr(attributes_t *attr){
335 	if(attr != NULL) {
336     	u_int16_t i;
337     	struct aspath *path, *pathstofree[3] = { attr->aspath, attr->old_aspath, attr->new_aspath };
338 	    for(i = 0; i < sizeof(pathstofree) / sizeof(pathstofree[0]); i++) {
339 	      path = pathstofree[i];
340 	      if(path) {
341 		if(path->data)
342 		  free(path->data);
343 		if(path->str)
344 		  free(path->str);
345 		free(path);
346 	      }
347 	    }
348 
349 	    if(attr->community != NULL) {
350 		if(attr->community->val != NULL)
351 		    free(attr->community->val);
352 
353 		if(attr->community->str != NULL)
354 		    free(attr->community->str);
355 
356 		free(attr->community);
357 	    }
358 
359         if(attr->lcommunity != NULL) {
360             if(attr->lcommunity->val != NULL)
361                 free(attr->lcommunity->val);
362 
363             if(attr->lcommunity->str != NULL)
364                 free(attr->lcommunity->str);
365 
366         free(attr->lcommunity);
367         }
368 
369 	    if(attr->data != NULL)
370 		free(attr->data);
371 
372 	    if(attr->mp_info != NULL)
373 		bgpdump_free_mp_info(attr->mp_info);
374 
375 	    if(attr->cluster != NULL) {
376 			free(attr->cluster->list);
377 			free(attr->cluster);
378 		}
379 
380 	    if (attr->unknown_num) {
381 		for (i = 0; i < attr->unknown_num; i++)
382 		    free(attr->unknown[i].raw);
383 		free(attr->unknown);
384 	    }
385 
386 	    free(attr);
387 	}
388 }
389 
390 /* Helper function to check if this is an Additional Paths enabled subtype (exported) */
is_addpath(BGPDUMP_ENTRY * entry)391 int is_addpath(BGPDUMP_ENTRY *entry) {
392     switch(entry->type) {
393         case BGPDUMP_TYPE_ZEBRA_BGP:
394         case BGPDUMP_TYPE_ZEBRA_BGP_ET:
395             switch(entry->subtype) {
396                 case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
397                 case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
398                 case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
399                 case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
400                     return 1;
401                 default:
402                     return 0;
403             }
404         case BGPDUMP_TYPE_TABLE_DUMP_V2:
405             switch(entry->subtype) {
406                 case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
407                 case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_MULTICAST_ADDPATH:
408                 case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
409                 case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_MULTICAST_ADDPATH:
410                 case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC_ADDPATH:
411                     return 1;
412                 default:
413                     return 0;
414             }
415         default:
416             return 0;
417     }
418 }
419 
process_mrtd_bgp(struct mstream * s,BGPDUMP_ENTRY * entry)420 int process_mrtd_bgp(struct mstream *s, BGPDUMP_ENTRY *entry) {
421     switch(entry->subtype) {
422     case BGPDUMP_SUBTYPE_MRTD_BGP_UPDATE:
423     case BGPDUMP_SUBTYPE_MRTD_BGP_KEEPALIVE:
424 	entry->body.mrtd_message.source_as = read_asn(s, ASN16_LEN);
425 	entry->body.mrtd_message.source_ip = mstream_get_ipv4(s);
426 
427 	entry->body.mrtd_message.destination_as = read_asn(s, ASN16_LEN);
428 	entry->body.mrtd_message.destination_ip = mstream_get_ipv4(s);
429 
430 	mstream_t withdraw_stream = mstream_copy(s, mstream_getw(s, NULL));
431 	entry->body.mrtd_message.withdraw_count = read_prefix_list(&withdraw_stream, AFI_IP,
432 								   entry->body.mrtd_message.withdraw,
433 								   &entry->body.mrtd_message.incomplete, 0);
434 
435 	if((entry->attr = process_attributes(s, ASN16_LEN, &entry->body.mrtd_message.incomplete, 0)) == NULL)
436 	    return 0;
437 
438 	entry->body.mrtd_message.announce_count = read_prefix_list(s, AFI_IP,
439 								   entry->body.mrtd_message.announce,
440 								   &entry->body.mrtd_message.incomplete, 0);
441 	break;
442     case BGPDUMP_SUBTYPE_MRTD_BGP_STATE_CHANGE:
443 	entry->body.mrtd_state_change.destination_as = read_asn(s, ASN16_LEN);
444 	entry->body.mrtd_state_change.destination_ip = mstream_get_ipv4(s);
445 	entry->body.mrtd_state_change.old_state = mstream_getw(s, NULL);
446 	entry->body.mrtd_state_change.new_state = mstream_getw(s, NULL);
447 	break;
448     }
449     return 1;
450 }
451 
process_mrtd_table_dump(struct mstream * s,BGPDUMP_ENTRY * entry)452 int process_mrtd_table_dump(struct mstream *s,BGPDUMP_ENTRY *entry) {
453     int afi = entry->subtype;
454     u_int8_t asn_len;
455     u_int32_t temp_time = 0;
456     mstream_getw(s,&entry->body.mrtd_table_dump.view);
457     mstream_getw(s,&entry->body.mrtd_table_dump.sequence);
458     switch(afi) {
459 	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP:
460 	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP_32BIT_AS:
461 	    entry->body.mrtd_table_dump.prefix.v4_addr = mstream_get_ipv4(s);
462 	    break;
463 #ifdef BGPDUMP_HAVE_IPV6
464 	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
465 	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
466 	    mstream_get(s, &entry->body.mrtd_table_dump.prefix.v6_addr.s6_addr, 16);
467 	    break;
468 #endif
469 	default:
470 	    warn("process_mrtd_table_dump: unknown AFI %d",  afi);
471 	    mstream_get(s, NULL, mstream_can_read(s));
472 	    return 0;
473     }
474     mstream_getc(s,&entry->body.mrtd_table_dump.mask);
475     mstream_getc(s,&entry->body.mrtd_table_dump.status);
476     mstream_getl(s,&temp_time);
477     (entry->body).mrtd_table_dump.uptime = temp_time;
478 
479     switch(afi) {
480       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP:
481       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP_32BIT_AS:
482 	entry->body.mrtd_table_dump.peer_ip.v4_addr = mstream_get_ipv4(s);
483 	break;
484 #ifdef BGPDUMP_HAVE_IPV6
485       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
486       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
487 	mstream_get(s, &entry->body.mrtd_table_dump.peer_ip.v6_addr.s6_addr, 16);
488 	break;
489 #endif
490     }
491 
492     switch(afi) {
493       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP:
494       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
495 	asn_len = ASN16_LEN;
496 	break;
497       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP_32BIT_AS:
498       case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
499 	asn_len = ASN32_LEN;
500 	break;
501       default:
502             assert(0); // unreachable
503     }
504 
505     entry->body.mrtd_table_dump.peer_as = read_asn(s, asn_len);
506 
507     if((entry->attr = process_attributes(s, asn_len, NULL, 0)) == NULL)
508         return 0;
509 
510     return 1;
511 }
512 
513 
process_mrtd_table_dump_v2(struct mstream * s,BGPDUMP_ENTRY * entry)514 int process_mrtd_table_dump_v2(struct mstream *s,BGPDUMP_ENTRY *entry) {
515 
516 	switch(entry->subtype){
517 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_PEER_INDEX_TABLE:
518 		return process_mrtd_table_dump_v2_peer_index_table(s, entry);
519 	break;
520 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST:
521 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV4_UNICAST_ADDPATH:
522 		return process_mrtd_table_dump_v2_ipv4_unicast(s, entry);
523 	break;
524 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST:
525 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_IPV6_UNICAST_ADDPATH:
526 		return process_mrtd_table_dump_v2_ipv6_unicast(s, entry);
527 	break;
528 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC:
529 	case BGPDUMP_SUBTYPE_TABLE_DUMP_V2_RIB_GENERIC_ADDPATH:
530 		//return process_mrtd_table_dump_v2_generic(s, entry);
531 	break;
532 	}
533 
534 	return 0;
535 }
536 
process_mrtd_table_dump_v2_peer_index_table(struct mstream * s,BGPDUMP_ENTRY * entry)537 int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY *entry) {
538 	BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE *t;
539 	uint16_t i;
540 	uint8_t peertype;
541 	uint16_t view_name_len;
542 
543 	if(entry->dump->table_dump_v2_peer_index_table) {
544 		free(entry->dump->table_dump_v2_peer_index_table->entries);
545 	}
546 	free(entry->dump->table_dump_v2_peer_index_table);
547 
548 	if((entry->dump->table_dump_v2_peer_index_table = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE))) == NULL) {
549 	    err("process_mrtd_table_dump_v2_peer_index_table: failed to allocate memory for index table");
550 	    return 0;
551 	}
552 	t = entry->dump->table_dump_v2_peer_index_table;
553 	t->entries = NULL;
554 
555 	t->local_bgp_id = mstream_get_ipv4(s);
556 
557 	mstream_getw(s,&view_name_len);
558 	strcpy(t->view_name, "");
559 
560 	// view_name_len is without trailing \0
561 	if(view_name_len+1 > BGPDUMP_TYPE_TABLE_DUMP_V2_MAX_VIEWNAME_LEN) {
562 	    warn("process_mrtd_table_dump_v2_peer_index_table: view name length more than maximum length (%d), ignoring view name", BGPDUMP_TYPE_TABLE_DUMP_V2_MAX_VIEWNAME_LEN);
563 	} else {
564 		mstream_get(s, t->view_name, view_name_len);
565 		t->view_name[view_name_len] = 0;
566 	}
567 
568 	mstream_getw(s,&t->peer_count);
569 
570 	t->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE_ENTRY) * t->peer_count);
571 	if(t->entries == NULL){
572 	    err("process_mrtd_table_dump_v2_peer_index_table: failed to allocate memory for index table");
573 		return 0;
574 	}
575 
576 	for(i=0; i < t->peer_count; i++) {
577     	mstream_getc(s,&peertype);
578                 t->entries[i].afi = AFI_IP;
579 #ifdef BGPDUMP_HAVE_IPV6
580 		if(peertype & BGPDUMP_PEERTYPE_TABLE_DUMP_V2_AFI_IP6)
581 			t->entries[i].afi = AFI_IP6;
582 #endif
583 
584                 t->entries[i].peer_bgp_id = mstream_get_ipv4(s);
585 
586 		if(t->entries[i].afi == AFI_IP)
587 			t->entries[i].peer_ip.v4_addr = mstream_get_ipv4(s);
588 #ifdef BGPDUMP_HAVE_IPV6
589 		else
590 			mstream_get(s, &t->entries[i].peer_ip.v6_addr.s6_addr, 16);
591 #endif
592 
593 
594 		if(peertype & BGPDUMP_PEERTYPE_TABLE_DUMP_V2_AS4)
595 			t->entries[i].peer_as = read_asn(s, ASN32_LEN);
596 		else
597 			t->entries[i].peer_as = read_asn(s, ASN16_LEN);
598 
599 	}
600 	return 0;
601 }
602 
603 
process_mrtd_table_dump_v2_ipv4_unicast(struct mstream * s,BGPDUMP_ENTRY * entry)604 int process_mrtd_table_dump_v2_ipv4_unicast(struct mstream *s, BGPDUMP_ENTRY *entry){
605 	BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
606 	prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
607     int addpath = is_addpath(entry);
608 	uint16_t i;
609 
610 	prefixdata->afi = AFI_IP;
611 	prefixdata->safi = SAFI_UNICAST;
612 
613 	mstream_getl(s, &prefixdata->seq);
614 	mstream_getc(s, &prefixdata->prefix_length);
615 	bzero(&prefixdata->prefix.v4_addr.s_addr, 4);
616 	mstream_get(s, &prefixdata->prefix.v4_addr.s_addr, (prefixdata->prefix_length+7)/8);
617 	mstream_getw(s, &prefixdata->entry_count);
618 
619 	prefixdata->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY) * prefixdata->entry_count);
620 	if(prefixdata->entries == NULL){
621 	    err("process_mrtd_table_dump_v2_ipv4_unicast: failed to allocate memory for entry table");
622 		return 0;
623 	}
624 
625 	if(prefixdata->entry_count && entry->dump->table_dump_v2_peer_index_table == NULL) {
626 	    free(prefixdata->entries);
627 	    err("%s: missing peer index table", __func__);
628 	    return 0;
629         }
630 
631 	for(i=0; i < prefixdata->entry_count; i++){
632 		BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
633 		e = &prefixdata->entries[i];
634 
635 		mstream_getw(s, &e->peer_index);
636 		assert(e->peer_index < entry->dump->table_dump_v2_peer_index_table->peer_count);
637 		e->peer = &entry->dump->table_dump_v2_peer_index_table->entries[e->peer_index];
638 		mstream_getl(s, &e->originated_time);
639 
640 		if (addpath)
641 		    mstream_getl(s, &e->path_id);
642 
643 		if((e->attr = process_attributes(s, 4, NULL, is_addpath(entry))) == NULL)
644 		    return 0;
645 	}
646 
647 	return 1;
648 }
649 
650 
process_mrtd_table_dump_v2_ipv6_unicast(struct mstream * s,BGPDUMP_ENTRY * entry)651 int process_mrtd_table_dump_v2_ipv6_unicast(struct mstream *s, BGPDUMP_ENTRY *entry){
652 #ifdef BGPDUMP_HAVE_IPV6
653 	BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
654 	prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
655     int addpath = is_addpath(entry);
656 	uint16_t i;
657 
658 	prefixdata->afi = AFI_IP6;
659 	prefixdata->safi = SAFI_UNICAST;
660 
661 	mstream_getl(s, &prefixdata->seq);
662 
663 	mstream_getc(s, &prefixdata->prefix_length);
664 	bzero(&prefixdata->prefix.v6_addr.s6_addr, 16);
665 	mstream_get(s, &prefixdata->prefix.v6_addr.s6_addr, (prefixdata->prefix_length+7)/8);
666 
667 	mstream_getw(s, &prefixdata->entry_count);
668 
669 	prefixdata->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY) * prefixdata->entry_count);
670 	if(prefixdata->entries == NULL){
671 	    err("process_mrtd_table_dump_v2_ipv6_unicast: failed to allocate memory for entry table");
672 		return 0;
673 	}
674 
675 	if(prefixdata->entry_count && entry->dump->table_dump_v2_peer_index_table == NULL) {
676 	    free(prefixdata->entries);
677 	    err("%s: missing peer index table", __func__);
678 	    return 0;
679         }
680 
681 	for(i=0; i < prefixdata->entry_count; i++){
682 		BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
683 		e = &prefixdata->entries[i];
684 
685 		mstream_getw(s, &e->peer_index);
686 		assert(e->peer_index < entry->dump->table_dump_v2_peer_index_table->peer_count);
687 		e->peer = &entry->dump->table_dump_v2_peer_index_table->entries[e->peer_index];
688 		mstream_getl(s, &e->originated_time);
689 
690 		if (addpath)
691 		    mstream_getl(s, &e->path_id);
692 
693 		if((e->attr = process_attributes(s, 4, NULL, is_addpath(entry))) == NULL)
694 		    return 0;
695 	}
696 
697 #endif
698 	return 1;
699 }
700 
process_zebra_bgp(struct mstream * s,BGPDUMP_ENTRY * entry)701 int process_zebra_bgp(struct mstream *s,BGPDUMP_ENTRY *entry) {
702     switch(entry->subtype) {
703 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_STATE_CHANGE:
704 	    return process_zebra_bgp_state_change(s, entry, ASN16_LEN);
705 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_STATE_CHANGE_AS4:
706 	    return process_zebra_bgp_state_change(s, entry, ASN32_LEN);
707 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
708 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
709     case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
710 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
711 	    return process_zebra_bgp_message(s, entry, ASN16_LEN);
712 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
713 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
714 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
715 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
716 	    return process_zebra_bgp_message(s, entry, ASN32_LEN);
717 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_ENTRY:
718 	    return process_zebra_bgp_entry(s,entry);
719 	case BGPDUMP_SUBTYPE_ZEBRA_BGP_SNAPSHOT:
720 	    return process_zebra_bgp_snapshot(s, entry);
721 	default:
722 	    warn("process_zebra_bgp: unknown subtype %d", entry->subtype);
723 	    return 0;
724     }
725 }
726 
process_zebra_bgp_state_change(struct mstream * s,BGPDUMP_ENTRY * entry,u_int8_t asn_len)727 int process_zebra_bgp_state_change(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
728     entry->body.zebra_state_change.source_as = read_asn(s, asn_len);
729     entry->body.zebra_state_change.destination_as = read_asn(s, asn_len);
730 
731     /* Work around Zebra dump corruption.
732      * N.B. I don't see this in quagga 0.96.4 any more. Is it fixed? */
733     if (entry->length == 8) {
734 	warn("process_zebra_bgp_state_change: 8-byte state change (zebra bug?)");
735 
736 	mstream_getw(s,&entry->body.zebra_state_change.old_state);
737 	mstream_getw(s,&entry->body.zebra_state_change.new_state);
738 
739 	/* Fill in with dummy values */
740 	entry->body.zebra_state_change.interface_index = 0;
741 	entry->body.zebra_state_change.address_family = AFI_IP;
742 	entry->body.zebra_state_change.source_ip.v4_addr.s_addr = 0;
743 	entry->body.zebra_state_change.destination_ip.v4_addr.s_addr = 0;
744 
745    	return 1;
746     }
747 
748     mstream_getw(s,&entry->body.zebra_state_change.interface_index);
749     mstream_getw(s,&entry->body.zebra_state_change.address_family);
750 
751     switch(entry->body.zebra_state_change.address_family) {
752 	case AFI_IP:
753 	    // length could be 20 or 24 (asn16 vs asn32)
754 	    if(entry->length != 20 && entry->length != 24) {
755 		warn("process_zebra_bgp_state_change: bad length %d",
756 		       entry->length);
757 		return 0;
758 	    }
759 
760 	    entry->body.zebra_state_change.source_ip.v4_addr = mstream_get_ipv4(s);
761 	    entry->body.zebra_state_change.destination_ip.v4_addr = mstream_get_ipv4(s);
762 	    break;
763 #ifdef BGPDUMP_HAVE_IPV6
764 	case AFI_IP6:
765 	    // length could be 44 or 48 (asn16 vs asn32)
766 	    if(entry->length != 44 && entry->length != 48) {
767 		warn("process_zebra_bgp_state_change: bad length %d",
768 		       entry->length);
769 		return 0;
770 	    }
771 
772 	    mstream_get(s, &entry->body.zebra_state_change.source_ip.v6_addr.s6_addr, 16);
773 	    mstream_get(s, &entry->body.zebra_state_change.destination_ip.v6_addr.s6_addr, 16);
774 	    break;
775 #endif
776 	default:
777 	    warn("process_zebra_bgp_state_change: unknown AFI %d",
778 		   entry->body.zebra_state_change.address_family);
779 	    return 0;
780     }
781     mstream_getw(s,&entry->body.zebra_state_change.old_state);
782     mstream_getw(s,&entry->body.zebra_state_change.new_state);
783 
784     return 1;
785 }
786 
process_zebra_bgp_message(struct mstream * s,BGPDUMP_ENTRY * entry,u_int8_t asn_len)787 int process_zebra_bgp_message(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
788     u_char marker[16]; /* BGP marker */
789 
790 	switch(entry->subtype) {
791 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
792 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
793 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
794 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
795 			entry->body.zebra_message.destination_as = read_asn(s, asn_len);
796 			entry->body.zebra_message.source_as = read_asn(s, asn_len);
797 			break;
798 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
799 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
800 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
801 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
802 		default:
803 			entry->body.zebra_message.source_as = read_asn(s, asn_len);
804 			entry->body.zebra_message.destination_as = read_asn(s, asn_len);
805 			break;
806 	}
807 
808     mstream_getw(s,&entry->body.zebra_message.interface_index);
809     mstream_getw(s,&entry->body.zebra_message.address_family);
810 
811     entry->body.zebra_message.opt_len = 0;
812     entry->body.zebra_message.opt_data = NULL;
813     entry->body.zebra_message.notify_len = 0;
814     entry->body.zebra_message.notify_data = NULL;
815 
816     switch(entry->body.zebra_message.address_family) {
817 	case AFI_IP:
818 		switch(entry->subtype) {
819 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
820 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
821 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
822 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
823 		    		entry->body.zebra_message.destination_ip.v4_addr = mstream_get_ipv4(s);
824 		    		entry->body.zebra_message.source_ip.v4_addr = mstream_get_ipv4(s);
825 				break;
826 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
827 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
828 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
829 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
830 			default:
831 				entry->body.zebra_message.source_ip.v4_addr = mstream_get_ipv4(s);
832 				entry->body.zebra_message.destination_ip.v4_addr = mstream_get_ipv4(s);
833 				break;
834 		}
835 	    mstream_get (s, marker, 16);
836 	    break;
837 #ifdef BGPDUMP_HAVE_IPV6
838 	case AFI_IP6:
839 		switch(entry->subtype) {
840 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL:
841 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL:
842 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_LOCAL_ADDPATH:
843 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_LOCAL_ADDPATH:
844 				mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
845 				mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
846 				break;
847 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
848 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
849 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_ADDPATH:
850 			case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4_ADDPATH:
851 			default:
852 				mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
853 				mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
854 				break;
855 		}
856 	    mstream_get (s, marker, 16);
857 	    break;
858 #endif
859 	case 0xFFFF:
860 	    /* Zebra doesn't dump ifindex or src/dest IPs in OPEN
861 	     * messages. Work around it. */
862 	    if (entry->body.zebra_message.interface_index == 0xFFFF) {
863 		memset(marker, 0xFF, 4);
864 		mstream_get (s, marker + 4, 12);
865 		entry->body.zebra_message.interface_index = 0;
866 		entry->body.zebra_message.address_family = AFI_IP;
867 		entry->body.zebra_message.source_ip.v4_addr.s_addr = 0;
868 		entry->body.zebra_message.destination_ip.v4_addr.s_addr = 0;
869 		break;
870 	    }
871 	    /* Note fall through! If we don't recognize this type of data corruption, we say
872 	     * the address family is unsupported (since FFFF is not a valid address family) */
873 	default:
874 	    /* unsupported address family */
875 	    warn("process_zebra_bgp_message: unsupported AFI %d",
876 		   entry->body.zebra_message.address_family);
877 	    return 0;
878     }
879 
880     if(memcmp(marker, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16) != 0) {
881 	/* bad marker... ignore packet */
882 	warn(
883 	       "bgp_message: bad marker: %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
884 	       marker[0],marker[1],marker[2],marker[3],marker[4],marker[5],marker[6],marker[7],
885 	       marker[8],marker[9],marker[10],marker[11],marker[12],marker[13],marker[14],marker[15]);
886 	return 0;
887     }
888 
889     mstream_getw(s,&entry->body.zebra_message.size);
890 
891     int expected = entry->body.zebra_message.size - sizeof(marker) - sizeof(u_int16_t);
892 
893     mstream_t copy = mstream_copy(s, expected);
894 
895     entry->body.zebra_message.cut_bytes = expected - mstream_can_read(&copy);
896 
897     switch(mstream_getc (&copy, &entry->body.zebra_message.type)) {
898 	case BGP_MSG_OPEN:
899 	    return process_zebra_bgp_message_open(&copy, entry, asn_len);
900 	case BGP_MSG_UPDATE:
901 	    return process_zebra_bgp_message_update(&copy, entry, asn_len);
902 	case BGP_MSG_NOTIFY:
903 	    return process_zebra_bgp_message_notify(&copy, entry);
904 	case BGP_MSG_KEEPALIVE:
905 	    /* Nothing to do */
906 	    return 1;
907 	case BGP_MSG_ROUTE_REFRESH_01:
908 	    /* Not implemented yet */
909 	    warn("bgp_message: MSG_ROUTE_REFRESH_01 not implemented yet");
910 	    return 0;
911 	case BGP_MSG_ROUTE_REFRESH:
912 	    /* Not implemented yet */
913 	    warn("bgp_message: MSG_ROUTE_REFRESH not implemented yet");
914 	    return 0;
915 	default:
916 	    warn("bgp_message: unknown BGP message type %d",
917 		   entry->body.zebra_message.type);
918 	    return 0;
919     }
920 }
921 
process_zebra_bgp_message_notify(struct mstream * s,BGPDUMP_ENTRY * entry)922 int process_zebra_bgp_message_notify(struct mstream *s, BGPDUMP_ENTRY *entry) {
923     mstream_getc(s, &entry->body.zebra_message.error_code);
924     mstream_getc(s, &entry->body.zebra_message.sub_error_code);
925     entry->body.zebra_message.notify_len = entry->body.zebra_message.size - 21;
926 
927     if(entry->body.zebra_message.notify_len > 0) {
928 	if((entry->body.zebra_message.notify_data = malloc(entry->body.zebra_message.notify_len)) == NULL) {
929             err("%s: out of memory", __func__);
930             return 0;
931         }
932 	mstream_get(s, entry->body.zebra_message.notify_data, entry->body.zebra_message.notify_len);
933     }
934 
935     return 1;
936 }
937 
process_zebra_bgp_message_open(struct mstream * s,BGPDUMP_ENTRY * entry,u_int8_t asn_len)938 int process_zebra_bgp_message_open(struct mstream *s, BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
939     mstream_getc(s, &entry->body.zebra_message.version);
940     // my_as in open is always 16bits, regardless of MRT subtype
941     entry->body.zebra_message.my_as = read_asn(s, ASN16_LEN);
942     mstream_getw(s, &entry->body.zebra_message.hold_time);
943     entry->body.zebra_message.bgp_id = mstream_get_ipv4(s);
944     mstream_getc(s, &entry->body.zebra_message.opt_len);
945 
946     if(entry->body.zebra_message.opt_len) {
947 	if((entry->body.zebra_message.opt_data = malloc(entry->body.zebra_message.opt_len)) == NULL) {
948 	    err("%s: out of memory", __func__);
949 	    return 0;
950 	}
951 
952 	mstream_get(s, entry->body.zebra_message.opt_data, entry->body.zebra_message.opt_len);
953     }
954 
955     return 1;
956 }
957 
process_zebra_bgp_message_update(struct mstream * s,BGPDUMP_ENTRY * entry,u_int8_t asn_len)958 int process_zebra_bgp_message_update(struct mstream *s, BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
959     entry->body.zebra_message.incomplete.orig_len = 0;
960 
961     mstream_t withdraw_stream = mstream_copy(s, mstream_getw(s, NULL));
962     entry->body.zebra_message.withdraw_count = read_prefix_list(&withdraw_stream, AFI_IP,
963                          entry->body.zebra_message.withdraw,
964 			 &entry->body.zebra_message.incomplete,
965              is_addpath(entry));
966 
967     if((entry->attr = process_attributes(s, asn_len, &entry->body.zebra_message.incomplete, is_addpath(entry))) == NULL)
968         return 0;
969 
970     entry->body.zebra_message.announce_count = read_prefix_list(s, AFI_IP,
971                          entry->body.zebra_message.announce,
972 			 &entry->body.zebra_message.incomplete,
973              is_addpath(entry));
974 
975     return 1;
976 }
977 
process_zebra_bgp_entry(struct mstream * s,BGPDUMP_ENTRY * entry)978 int process_zebra_bgp_entry(struct mstream *s, BGPDUMP_ENTRY *entry) {
979     warn("process_zebra_bgp_entry: record type not implemented yet");
980     return 0;
981 }
982 
process_zebra_bgp_snapshot(struct mstream * s,BGPDUMP_ENTRY * entry)983 int process_zebra_bgp_snapshot(struct mstream *s, BGPDUMP_ENTRY *entry) {
984     warn("process_zebra_bgp_snapshot: record type not implemented yet");
985     return 0;
986 }
987 
attr_init(struct mstream * s,int len)988 static attributes_t *attr_init(struct mstream *s, int len) {
989 
990     attributes_t *attr = malloc(sizeof(struct attr));
991 
992     if(attr == NULL) {
993         err("%s: out of memory", __func__);
994         return NULL;
995     }
996     if((attr->data=malloc(len)) == NULL) {
997         free(attr);
998         err("%s: out of memory", __func__);
999         return NULL;
1000     }
1001     memcpy(attr->data, &s->start[s->position], len);
1002 
1003     attr->len = len;
1004     attr->flag			= 0;
1005     attr->origin		= -1;
1006     attr->nexthop.s_addr	= INADDR_NONE;
1007     attr->med			= -1;
1008     attr->local_pref		= -1;
1009     attr->aggregator_as		= -1;
1010     attr->aggregator_addr.s_addr = INADDR_NONE;
1011     attr->weight		= -1;
1012 
1013     attr->originator_id.s_addr	= -1;
1014     attr->cluster		= NULL;
1015 
1016     attr->aspath			= NULL;
1017     attr->community		= NULL;
1018     attr->lcommunity     = NULL;
1019 
1020     attr->transit		= NULL;
1021     attr->mp_info		= calloc(1, sizeof(struct mp_info));
1022     if(attr->mp_info == NULL) {
1023         free(attr->data);
1024         free(attr);
1025         err("%s: out of memory", __func__);
1026         return NULL;
1027     }
1028     attr->unknown_num = 0;
1029     attr->unknown = NULL;
1030 
1031     attr->new_aspath		= NULL;
1032     attr->old_aspath		= NULL;
1033     attr->new_aggregator_as	= -1;
1034     attr->new_aggregator_addr.s_addr = INADDR_NONE;
1035 
1036     return attr;
1037 }
1038 
process_unknown_attr(struct mstream * s,attributes_t * attr,int flag,int type,int len)1039 static void process_unknown_attr(struct mstream *s, attributes_t *attr, int flag, int type, int len) {
1040     /* Unknown attribute. Save as is */
1041     attr->unknown_num++;
1042     if((attr->unknown = realloc(attr->unknown, attr->unknown_num * sizeof(struct unknown_attr))) == NULL) {
1043         err("%s: out of memory", __func__);
1044         exit(1); /* XXX */
1045     }
1046 
1047     /* Pointer to the unknown attribute we want to fill in */
1048     struct unknown_attr unknown = {
1049         .flag = flag,
1050         .type = type,
1051         .len = len,
1052         .raw = malloc(len)
1053     };
1054     if(unknown.raw == NULL) {
1055         err("%s: out of memory", __func__);
1056         exit(1); /* XXX */
1057     }
1058     attr->unknown[attr->unknown_num - 1] = unknown;
1059 
1060     mstream_get(s, unknown.raw, len);
1061 }
1062 
process_one_attr(struct mstream * outer_stream,attributes_t * attr,u_int8_t asn_len,struct zebra_incomplete * incomplete,int is_addp)1063 static void process_one_attr(struct mstream *outer_stream, attributes_t *attr, u_int8_t asn_len, struct zebra_incomplete *incomplete, int is_addp) {
1064     int flag = mstream_getc(outer_stream, NULL);
1065     int type = mstream_getc(outer_stream, NULL);
1066     int len;
1067 
1068     if(flag & BGP_ATTR_FLAG_EXTLEN)
1069         len = mstream_getw(outer_stream,NULL);
1070     else
1071         len = mstream_getc(outer_stream,NULL);
1072 
1073     //info("flag:%-2i type:%-2i length:%i", flag, type, len);
1074 
1075     mstream_t ms = mstream_copy(outer_stream, len), *s = &ms;
1076     if(mstream_can_read(s) != len) {
1077         warn("ERROR attribute is truncated: expected=%u remaining=%u\n", len, mstream_can_read(s));
1078         return;
1079     }
1080 
1081     /* Take note of all attributes, including unknown ones */
1082     if(type <= sizeof(attr->flag) * 8)
1083         attr->flag |= ATTR_FLAG_BIT(type);
1084 
1085     switch(type) {
1086         case BGP_ATTR_MP_REACH_NLRI:
1087             process_mp_announce(s, attr->mp_info, incomplete, is_addp);
1088             break;
1089         case BGP_ATTR_MP_UNREACH_NLRI:
1090             process_mp_withdraw(s, attr->mp_info, incomplete, is_addp);
1091             break;
1092         case BGP_ATTR_ORIGIN:
1093             assert(attr->origin == -1);
1094             attr->origin = mstream_getc(s, NULL);
1095             break;
1096         case BGP_ATTR_AS_PATH:
1097             assert(! attr->aspath);
1098             attr->aspath = create_aspath(len, asn_len);
1099             mstream_get(s, attr->aspath->data, len);
1100             process_attr_aspath_string(attr->aspath);
1101             break;
1102         case BGP_ATTR_NEXT_HOP:
1103             assert(INADDR_NONE == attr->nexthop.s_addr);
1104             attr->nexthop = mstream_get_ipv4(s);
1105             break;
1106         case BGP_ATTR_MULTI_EXIT_DISC:
1107             assert(-1 == attr->med);
1108             mstream_getl(s,&attr->med);
1109             break;
1110         case BGP_ATTR_LOCAL_PREF:
1111             assert(-1 == attr->local_pref);
1112             mstream_getl(s,&attr->local_pref);
1113             break;
1114         case BGP_ATTR_ATOMIC_AGGREGATE:
1115             break;
1116         case BGP_ATTR_AGGREGATOR:
1117             assert(-1 == attr->new_aggregator_as);
1118             attr->aggregator_as = read_asn(s, asn_len);
1119             attr->aggregator_addr = mstream_get_ipv4(s);
1120             break;
1121         case BGP_ATTR_COMMUNITIES:
1122             assert(! attr->community);
1123             if((attr->community		= malloc(sizeof(struct community))) == NULL) {
1124                 err("%s: out of memory", __func__);
1125                 exit(1); /* XXX */
1126             }
1127 
1128             attr->community->size	= len / 4;
1129             if((attr->community->val	= malloc(len)) == NULL) {
1130                 err("%s: out of memory", __func__);
1131                 exit(1); /* XXX */
1132             }
1133 
1134             mstream_get(s,attr->community->val,len);
1135             attr->community->str	= NULL;
1136             process_attr_community_string(attr->community);
1137             break;
1138          case BGP_ATTR_LARGE_COMMUNITIES:
1139             assert(! attr->lcommunity);
1140             if((attr->lcommunity     = malloc(sizeof(struct lcommunity))) == NULL) {
1141                 err("%s: out of memory", __func__);
1142                 exit(1); /* XXX */
1143             }
1144 
1145             attr->lcommunity->size   = len / 12;
1146             if((attr->lcommunity->val    = malloc(len)) == NULL) {
1147                 err("%s: out of memory", __func__);
1148                 exit(1); /* XXX */
1149             }
1150 
1151             mstream_get(s,attr->lcommunity->val,len);
1152             attr->lcommunity->str    = NULL;
1153             process_attr_lcommunity_string(attr->lcommunity);
1154             break;
1155         case BGP_ATTR_NEW_AS_PATH:
1156             assert(! attr->new_aspath);
1157             attr->new_aspath = create_aspath(len, ASN32_LEN);
1158             mstream_get(s,attr->new_aspath->data, len);
1159             process_attr_aspath_string(attr->new_aspath);
1160             /* AS_CONFED_SEQUENCE and AS_CONFED_SET segments invalid in NEW_AS_PATH */
1161             check_new_aspath(attr->new_aspath);
1162             break;
1163         case BGP_ATTR_NEW_AGGREGATOR:
1164             assert(-1 == attr->new_aggregator_as);
1165             attr->new_aggregator_as = read_asn(s, ASN32_LEN);
1166             attr->new_aggregator_addr = mstream_get_ipv4(s);
1167             break;
1168         case BGP_ATTR_ORIGINATOR_ID:
1169             assert(INADDR_NONE == attr->originator_id.s_addr);
1170             attr->originator_id = mstream_get_ipv4(s);
1171             break;
1172         case BGP_ATTR_CLUSTER_LIST:
1173             assert(! attr->cluster);
1174             if((attr->cluster= malloc(sizeof(struct cluster_list))) == NULL) {
1175                 err("%s: out of memory", __func__);
1176                 exit(1); /* XXX */
1177             }
1178             attr->cluster->length	= len/4;
1179             if((attr->cluster->list = calloc((attr->cluster->length), sizeof(struct in_addr))) == NULL) {
1180                 err("%s: out of memory", __func__);
1181                 exit(1); /* XXX */
1182             }
1183 
1184             int i; // cluster index
1185             for (i = 0; i < attr->cluster->length; i++)
1186                 attr->cluster->list[i] = mstream_get_ipv4(s);
1187             break;
1188         default:
1189             process_unknown_attr(s, attr, flag, type, len);
1190     }
1191 }
1192 
process_attributes(struct mstream * s,u_int8_t asn_len,struct zebra_incomplete * incomplete,int is_addp)1193 attributes_t *process_attributes(struct mstream *s, u_int8_t asn_len, struct zebra_incomplete *incomplete, int is_addp) {
1194     int	total = mstream_getw(s, NULL);
1195 
1196     attributes_t *attr = attr_init(s, total);
1197     if(attr == NULL)
1198         return NULL;
1199 
1200     mstream_t copy = mstream_copy(s, total);
1201 
1202     if(mstream_can_read(&copy) != total)
1203         warn("entry is truncated: expected=%u remaining=%u", total, mstream_can_read(&copy));
1204 
1205     while(mstream_can_read(&copy))
1206         process_one_attr(&copy, attr, asn_len, incomplete, is_addp);
1207 
1208     // Once all attributes have been read, take care of ASN32 transition
1209     process_asn32_trans(attr, asn_len);
1210 
1211     return attr;
1212 }
1213 
create_aspath(u_int16_t len,u_int8_t asn_len)1214 struct aspath *create_aspath(u_int16_t len, u_int8_t asn_len) {
1215   struct aspath *aspath = malloc(sizeof(struct aspath));
1216   if(aspath) {
1217     aspath->asn_len	= asn_len;
1218     aspath->length	= len;
1219     aspath->count	= 0;
1220     aspath->str		= NULL;
1221     if(len > 0) {
1222        if((aspath->data	= malloc(len)) == NULL) {
1223          err("%s: out of memory", __func__);
1224          free(aspath);
1225          return NULL;
1226        }
1227     } else
1228        aspath->data	= NULL;
1229   } else
1230       err("%s: out of memory", __func__);
1231   return aspath;
1232 }
1233 
aspath_error(struct aspath * as)1234 void aspath_error(struct aspath *as) {
1235   as->count = 0;
1236 
1237   if(as->str) {
1238     free(as->str);
1239     as->str = NULL;
1240   }
1241 
1242   as->str = malloc(strlen(ASPATH_STR_ERROR) + 1);
1243   if (as->str != NULL)
1244     strcpy(as->str, ASPATH_STR_ERROR);
1245 }
1246 
process_attr_aspath_string(struct aspath * as)1247 void process_attr_aspath_string(struct aspath *as) {
1248     const int MAX_ASPATH_LEN = 8000;
1249     if((as->str = malloc(MAX_ASPATH_LEN)) == NULL) {
1250         err("%s: out of memory", __func__);
1251         exit(1); /* XXX */
1252     }
1253 
1254     /* Set default values */
1255     int space = 0;
1256     u_char type = AS_SEQUENCE;
1257     int pos = 0;
1258 
1259     /* Set initial pointer. */
1260     caddr_t pnt = as->data;
1261     caddr_t end = pnt + as->length;
1262     struct assegment *segment = NULL;
1263 
1264     while (pnt < end) {
1265       int i;
1266 
1267       /* For fetch value. */
1268       segment = (struct assegment *) pnt;
1269 
1270       /* Check AS type validity. */
1271       if ((segment->type != AS_SET) &&
1272 	  (segment->type != AS_SEQUENCE) &&
1273 	  (segment->type != AS_CONFED_SET) &&
1274 	  (segment->type != AS_CONFED_SEQUENCE))
1275 	{
1276 	  aspath_error(as);
1277 	  return;
1278 	}
1279 
1280       /* Check AS length. */
1281       if ((pnt + (segment->length * as->asn_len) + AS_HEADER_SIZE) > end)
1282 	{
1283 	  aspath_error(as);
1284 	  return;
1285 	}
1286 
1287       /* If segment type is changed, print previous type's end
1288          character. */
1289       if (type != AS_SEQUENCE)
1290 	as->str[pos++] = aspath_delimiter_char (type, AS_SEG_END);
1291       if (space)
1292 	as->str[pos++] = ' ';
1293 
1294       if (segment->type != AS_SEQUENCE)
1295 	as->str[pos++] = aspath_delimiter_char (segment->type, AS_SEG_START);
1296 
1297       space = 0;
1298 
1299       /* Increment as->count - NOT ignoring CONFED_SETS/SEQUENCES any more.
1300          I doubt anybody was relying on this behaviour anyway. */
1301       switch(segment->type) {
1302 	case AS_SEQUENCE:
1303 	case AS_CONFED_SEQUENCE:
1304 	  as->count += segment->length;
1305 	break;
1306 	case AS_SET:
1307 	case AS_CONFED_SET:
1308 	  as->count += 1;
1309 	break;
1310       }
1311 
1312       for (i = 0; i < segment->length; i++)
1313 	{
1314 	  as_t asn;
1315 
1316 	  if (space)
1317 	    {
1318 	      if (segment->type == AS_SET
1319 		  || segment->type == AS_CONFED_SET)
1320 		as->str[pos++] = ',';
1321 	      else
1322 		as->str[pos++] = ' ';
1323 	    }
1324 	  else
1325 	    space = 1;
1326 
1327 	  int asn_pos = i * as->asn_len;
1328           switch(as->asn_len) {
1329                 case ASN16_LEN:
1330                     asn = ntohs (*(u_int16_t *) (segment->data + asn_pos));
1331                     break;
1332                 case ASN32_LEN:
1333                     asn = ntohl (*(u_int32_t *) (segment->data + asn_pos));
1334                     break;
1335                 default:
1336                     assert("invalid asn_len" && false);
1337           }
1338 
1339           pos += int2str(asn, as->str + pos);
1340           if(pos > MAX_ASPATH_LEN - 100) {
1341               strcpy(as->str + pos, "...");
1342               return;
1343           };
1344 	}
1345 
1346       type = segment->type;
1347       pnt += (segment->length * as->asn_len) + AS_HEADER_SIZE;
1348     }
1349 
1350   if (segment && segment->type != AS_SEQUENCE)
1351     as->str[pos++] = aspath_delimiter_char (segment->type, AS_SEG_END);
1352 
1353   as->str[pos] = '\0';
1354 }
1355 
aspath_delimiter_char(u_char type,u_char which)1356 char aspath_delimiter_char (u_char type, u_char which) {
1357   int i;
1358   struct
1359   {
1360     int type;
1361     char start;
1362     char end;
1363   } aspath_delim_char [] =
1364     {
1365       { AS_SET,             '{', '}' },
1366       { AS_SEQUENCE,        ' ', ' ' },
1367       { AS_CONFED_SET,      '[', ']' },
1368       { AS_CONFED_SEQUENCE, '(', ')' },
1369       { 0, '\0', '\0' }
1370     };
1371 
1372   for (i = 0; aspath_delim_char[i].type != 0; i++)
1373     {
1374       if (aspath_delim_char[i].type == type)
1375 	{
1376 	  if (which == AS_SEG_START)
1377 	    return aspath_delim_char[i].start;
1378 	  else if (which == AS_SEG_END)
1379 	    return aspath_delim_char[i].end;
1380 	}
1381     }
1382   return ' ';
1383 }
1384 
1385 
process_attr_community_string(struct community * com)1386 void process_attr_community_string(struct community *com) {
1387 
1388   char buf[BUFSIZ];
1389   int i;
1390   u_int32_t comval;
1391   u_int16_t as;
1392   u_int16_t val;
1393 
1394   memset (buf, 0, BUFSIZ);
1395 
1396   for (i = 0; i < com->size; i++)
1397     {
1398       memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
1399       comval = ntohl (comval);
1400       switch (comval)
1401 	{
1402 	case COMMUNITY_NO_EXPORT:
1403 	  strlcat (buf, " no-export", BUFSIZ);
1404 	  break;
1405 	case COMMUNITY_NO_ADVERTISE:
1406 	  strlcat (buf, " no-advertise", BUFSIZ);
1407 	  break;
1408 	case COMMUNITY_LOCAL_AS:
1409 	  strlcat (buf, " local-AS", BUFSIZ);
1410 	  break;
1411 	default:
1412 	  as = (comval >> 16) & 0xFFFF;
1413 	  val = comval & 0xFFFF;
1414 	  snprintf (buf + strlen (buf), BUFSIZ - strlen (buf),
1415 		    " %d:%d", as, val);
1416 	  break;
1417 	}
1418     }
1419 
1420     if((com->str = malloc(strlen(buf)+1)) != NULL) {
1421         strcpy(com->str, buf);
1422     } else {
1423         err("%s: out of memory", __func__);
1424         exit(1); /* XXX */
1425     }
1426 }
1427 
process_attr_lcommunity_string(struct lcommunity * lcom)1428 void process_attr_lcommunity_string(struct lcommunity *lcom) {
1429 
1430   char buf[BUFSIZ];
1431   u_int32_t i;
1432   u_int32_t global;
1433   u_int32_t local1;
1434   u_int32_t local2;
1435 
1436   memset (buf, 0, BUFSIZ);
1437 
1438   for (i = 0; i < lcom->size; i++)
1439     {
1440         memcpy (&global, lcom->val + (i * 3), sizeof (u_int32_t));
1441         memcpy (&local1, lcom->val + (i * 3) + 1, sizeof (u_int32_t));
1442         memcpy (&local2, lcom->val + (i * 3) + 2, sizeof (u_int32_t));
1443 
1444         global = ntohl (global);
1445         local1 = ntohl (local1);
1446         local2 = ntohl (local2);
1447 
1448         snprintf (buf + strlen (buf), BUFSIZ - strlen (buf),
1449             " %u:%u:%u", global, local1, local2);
1450     }
1451 
1452     if((lcom->str = malloc(strlen(buf)+1)) != NULL) {
1453         strcpy(lcom->str, buf);
1454     } else {
1455         err("%s: out of memory", __func__);
1456         exit(1); /* XXX */
1457     }
1458 
1459 }
1460 
get_nexthop(struct mstream * s)1461 static struct mp_nlri *get_nexthop(struct mstream *s) {
1462     struct mp_nlri *nlri = calloc(1, sizeof(struct mp_nlri));
1463 
1464     if(nlri == NULL) {
1465         err("%s: out of memory", __func__);
1466         return NULL;
1467     }
1468     nlri->nexthop_len = mstream_getc(s, NULL);
1469 
1470     // sometimes nexthop_len is 0 - not sure what this means (see IS-626)
1471     // if(mp_nlri->nexthop_len == 0)
1472     //    return len;
1473 
1474     // the AFI is irrelevant to the nexthop, since RFC5549
1475     // so this code now just checks for an expected length:
1476     // 4 = IPv4
1477     // 16 = IPv6
1478     // 32 = IPv6 + link-local
1479 
1480     if(nlri->nexthop_len == 4) {
1481         nlri->nexthop.v4_addr = mstream_get_ipv4(s);
1482     } else if(nlri->nexthop_len == 16) {
1483         mstream_get(s, &nlri->nexthop.v6_addr, 16);
1484     } else if(nlri->nexthop_len == 32) {
1485         mstream_get(s, &nlri->nexthop.v6_addr, 16);
1486         mstream_get(s, &nlri->nexthop_local.v6_addr.s6_addr, 16);
1487     }
1488     else {
1489         warn("process_mp_announce: unknown MP nexthop length %d", nlri->nexthop_len);
1490     }
1491     return nlri;
1492 }
1493 
process_mp_announce(struct mstream * s,struct mp_info * info,struct zebra_incomplete * incomplete,int is_addp)1494 void process_mp_announce(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp) {
1495     u_int16_t afi;
1496     u_int8_t safi;
1497 
1498     // look for MRT abbreviated MP_NLRI packets
1499     if(s->start[s->position] != 0) {
1500         assert(info->announce[AFI_IP6][SAFI_UNICAST] == NULL);
1501         info->announce[AFI_IP6][SAFI_UNICAST] = get_nexthop(s);
1502         return;
1503     }
1504 
1505     mstream_getw(s, &afi);
1506     mstream_getc(s, &safi);
1507 
1508     if(afi > BGPDUMP_MAX_AFI || safi > BGPDUMP_MAX_SAFI) {
1509             warn("process_mp_announce: unknown protocol(AFI=%d, SAFI=%d)!", afi, safi);
1510             return;
1511     }
1512 
1513     if(info->announce[afi][safi] != NULL) {
1514             warn("process_mp_announce: two MP_NLRI for the same protocol(%d, %d)!", afi, safi);
1515             return;
1516     }
1517 
1518     info->announce[afi][safi] = get_nexthop(s);
1519 
1520     // SNPA is defunct and num_snpa should always be 0
1521     u_int8_t num_snpa;
1522     if(mstream_getc(s, &num_snpa))
1523         warn("process_mp_announce: MP_NLRI contains SNPAs, skipping");
1524     for(; num_snpa > 0; --num_snpa) {
1525         mstream_get(s, NULL, mstream_getc(s, NULL));
1526     }
1527 
1528     info->announce[afi][safi]->prefix_count = read_prefix_list(s, afi, info->announce[afi][safi]->nlri, incomplete, is_addp);
1529 }
1530 
process_mp_withdraw(struct mstream * s,struct mp_info * info,struct zebra_incomplete * incomplete,int is_addp)1531 void process_mp_withdraw(struct mstream *s, struct mp_info *info, struct zebra_incomplete *incomplete, int is_addp) {
1532 	u_int16_t afi;
1533 	u_int8_t safi;
1534 	struct mp_nlri *mp_nlri;
1535 
1536 	mstream_getw(s, &afi);
1537 	mstream_getc(s, &safi);
1538 
1539 	/* Do we know about this address family? */
1540 	if(afi > BGPDUMP_MAX_AFI || safi > BGPDUMP_MAX_SAFI) {
1541 		warn("process_mp_withdraw: unknown AFI,SAFI %d,%d!", afi, safi);
1542 		return;
1543 	}
1544 
1545 	/* If there are 2 NLRI's for the same protocol, fail but don't burn and die */
1546 	if(info->withdraw[afi][safi] != NULL) {
1547 		warn("process_mp_withdraw: update contains more than one MP_NLRI with AFI,SAFI %d,%d!", afi, safi);
1548 		return;
1549 	}
1550 
1551 	/* Allocate structure */
1552 	if((mp_nlri = malloc(sizeof(struct mp_nlri))) == NULL) {
1553 	    err("%s: out of memory", __func__);
1554 	    exit(1); /* XXX */
1555 	}
1556 	memset(mp_nlri, 0, sizeof(struct mp_nlri));
1557 	info->withdraw[afi][safi] = mp_nlri;
1558 
1559 	mp_nlri->prefix_count = read_prefix_list(s, afi, mp_nlri->nlri, incomplete, is_addp);
1560 }
1561 
read_prefix_list(struct mstream * s,u_int16_t afi,struct prefix * prefixes,struct zebra_incomplete * incomplete,int is_addp)1562 static int read_prefix_list(struct mstream *s, u_int16_t afi, struct prefix *prefixes, struct zebra_incomplete *incomplete, int is_addp) {
1563     int count = 0;
1564 
1565     while(mstream_can_read(s)) {
1566 
1567         /* If this is an Additional Paths enabled NLRI, then there is a
1568          * 4 octet identifier preceeding each prefix entry */
1569         pathid_t path_id = 0;
1570         if (is_addp)
1571             path_id = mstream_getl(s, NULL);
1572 
1573         u_int8_t p_len = mstream_getc(s,NULL); // length in bits
1574         u_int8_t p_bytes = (p_len + 7) / 8;
1575 
1576         /* Truncated prefix list? */
1577         if(mstream_can_read(s) < p_bytes) {
1578             if(! incomplete)
1579                 break;
1580 
1581             /* Put prefix in incomplete structure */
1582             incomplete->afi = afi;
1583             incomplete->orig_len = p_len;
1584             incomplete->prefix = (struct prefix) {
1585                 .len = mstream_can_read(s) * 8,
1586                 .path_id = path_id
1587             };
1588             mstream_get(s, &incomplete->prefix.address, p_bytes);
1589             break;
1590         }
1591 
1592         struct prefix *prefix = prefixes + count;
1593 
1594         if(count++ > MAX_PREFIXES)
1595             continue;
1596 
1597         *prefix = (struct prefix) { .len = p_len, .path_id = path_id };
1598         mstream_get(s, &prefix->address, p_bytes);
1599     }
1600 
1601     if(count > MAX_PREFIXES) {
1602         err("too many prefixes (%i > %i)", count, MAX_PREFIXES);
1603         return MAX_PREFIXES;
1604     }
1605 
1606     return count;
1607 }
1608 
read_asn(struct mstream * s,u_int8_t len)1609 static as_t read_asn(struct mstream *s, u_int8_t len) {
1610   assert(len == ASN32_LEN || len == ASN16_LEN);
1611   switch(len) {
1612     case ASN32_LEN:
1613       return mstream_getl(s, NULL);
1614     case ASN16_LEN:
1615       return mstream_getw(s, NULL);
1616     default:
1617       /* Not reached. Avoid compiler warning */
1618       return 0;
1619   }
1620 }
1621 
check_new_aspath(struct aspath * aspath)1622 int check_new_aspath(struct aspath *aspath) {
1623   struct assegment *segment;
1624   for(segment = (struct assegment *) aspath->data;
1625       segment < (struct assegment *) (aspath->data + aspath->length);
1626       segment = (struct assegment *) ((char *) segment + sizeof(*segment) + segment->length * ASN32_LEN)) {
1627     if(segment->type == AS_CONFED_SEQUENCE || segment->type == AS_CONFED_SET) {
1628       warn("check_new_aspath: invalid segment of type AS_CONFED_%s in NEW_AS_PATH",
1629 	     segment->type == AS_CONFED_SET ? "SET" : "SEQUENCE");
1630       return 0;
1631     }
1632   }
1633   return 1;
1634 }
1635 
process_asn32_trans(attributes_t * attr,u_int8_t asn_len)1636 void process_asn32_trans(attributes_t *attr, u_int8_t asn_len) {
1637   if(asn_len == ASN32_LEN) {
1638     /* These attributes "SHOULD NOT" be used with ASN32. */
1639     if(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AS_PATH))
1640       warn("process_asn32_trans: ASN32 message contains NEW_AS_PATH attribute");
1641 
1642     if(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AGGREGATOR))
1643       warn("process_asn32_trans: ASN32 message contains NEW_AGGREGATOR attribute");
1644 
1645     /* Don't compute anything, just leave AS_PATH and AGGREGATOR as they are */
1646     return;
1647   }
1648 
1649   /* Process NEW_AGGREGATOR */
1650   if(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR) &&
1651      attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AGGREGATOR)) {
1652       /* Both AGGREGATOR and NEW_AGGREGATOR present, merge */
1653       if(attr->aggregator_as != AS_TRAN) {
1654 	/* Don't do anything */
1655 	return;
1656       } else {
1657 	attr->old_aggregator_as = attr->aggregator_as;
1658 	attr->old_aggregator_addr = attr->aggregator_addr;
1659 	attr->aggregator_as = attr->new_aggregator_as;
1660 	attr->aggregator_addr = attr->new_aggregator_addr;
1661       }
1662   }
1663 
1664   /* Process NEW_AS_PATH */
1665   if(! (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AS_PATH)))
1666     return;
1667 
1668   // attr->aspath may be NULL, at least in case of MP_UNREACH_NLRI
1669   if(attr->aspath == NULL) return;
1670   if(attr->aspath->count < attr->new_aspath->count) {
1671     return;
1672   }
1673 
1674   /* Merge paths */
1675   attr->old_aspath = attr->aspath;
1676   attr->aspath = asn32_merge_paths(attr->old_aspath, attr->new_aspath);
1677   if(attr->aspath) {
1678     process_attr_aspath_string(attr->aspath);
1679   }
1680 }
1681 
asn32_merge_paths(struct aspath * path,struct aspath * newpath)1682 struct aspath *asn32_merge_paths(struct aspath *path, struct aspath *newpath) {
1683   void *tmp;
1684   struct aspath *mergedpath = create_aspath(0, ASN32_LEN);
1685   if(mergedpath == NULL)
1686       return NULL;
1687   struct assegment *segment, *mergedsegment;
1688   int newlen;
1689 
1690   /* Keep copying segments from AS_PATH until our path is as long as AS_PATH - NEW_AS_PATH. */
1691   segment = (struct assegment *) (path->data);
1692   while(mergedpath->count < path->count - newpath->count) {
1693     /* Make room */
1694     newlen = mergedpath->length + sizeof(struct assegment) + segment->length * ASN32_LEN;
1695     tmp = realloc(mergedpath->data, newlen);
1696     if(tmp == NULL) {
1697         free(mergedpath->data);
1698         free(mergedpath);
1699         err("%s: out of memory", __func__);
1700         return NULL;
1701     }
1702     mergedpath->data = tmp;
1703 
1704     /* Create a new AS-path segment */
1705     mergedsegment = (struct assegment *) (mergedpath->data + mergedpath->length);
1706 
1707     /* Copy segment over. AS_PATH contains 16-bit ASes, so expand */
1708     mergedsegment->type = segment->type;
1709     mergedsegment->length = segment->length;
1710     asn32_expand_16_to_32(mergedsegment->data, segment->data, segment->length);
1711 
1712     /* Update length */
1713     mergedpath->length = newlen;
1714     if(segment->type == AS_SET || segment->type == AS_CONFED_SET) {
1715       mergedpath->count += 1;
1716     } else {
1717       mergedpath->count += segment->length;
1718       /* Did we copy too many ASes over? */
1719       if(mergedpath->count > path->count - newpath->count) {
1720 	mergedsegment->length -= mergedpath->count - (path->count - newpath->count);
1721 	mergedpath->length -= (mergedpath->count - (path->count - newpath->count)) * ASN32_LEN;
1722       }
1723     }
1724   }
1725 
1726   /* Append NEW_AS_PATH to merged path */
1727   tmp = realloc(mergedpath->data, mergedpath->length + newpath->length);
1728   if(tmp == NULL) {
1729       free(mergedpath->data);
1730       free(mergedpath);
1731       err("%s: out of memory", __func__);
1732       return NULL;
1733   }
1734   mergedpath->data = tmp;
1735   memcpy(mergedpath->data + mergedpath->length, newpath->data, newpath->length);
1736   mergedpath->length += newpath->length;
1737 
1738   return mergedpath;
1739 }
1740 
asn32_expand_16_to_32(char * dst,char * src,int len)1741 void asn32_expand_16_to_32(char *dst, char *src, int len) {
1742   u_int32_t *dstarray = (u_int32_t *) dst;
1743   u_int16_t *srcarray = (u_int16_t *) src;
1744   int i;
1745 
1746   for(i = 0; i < len; i++) {
1747     dstarray[i] = htonl(ntohs(srcarray[i]));
1748   }
1749 }
1750 
1751 #if defined(linux)
strlcat(char * dst,const char * src,size_t size)1752 size_t strlcat(char *dst, const char *src, size_t size) {
1753   if (strlen (dst) + strlen (src) >= size)
1754     return -1;
1755 
1756   strcat (dst, src);
1757 
1758   return (strlen(dst));
1759 }
1760 #endif
1761 
1762