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(©);
896
897 switch(mstream_getc (©, &entry->body.zebra_message.type)) {
898 case BGP_MSG_OPEN:
899 return process_zebra_bgp_message_open(©, entry, asn_len);
900 case BGP_MSG_UPDATE:
901 return process_zebra_bgp_message_update(©, entry, asn_len);
902 case BGP_MSG_NOTIFY:
903 return process_zebra_bgp_message_notify(©, 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(©) != total)
1203 warn("entry is truncated: expected=%u remaining=%u", total, mstream_can_read(©));
1204
1205 while(mstream_can_read(©))
1206 process_one_attr(©, 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