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 Author: Dan Ardelean (dan@ripe.net)
26 */
27 
28 #include "bgpdump_lib.h"
29 #include <time.h>
30 
31 #include <stdlib.h>
32 #include <netinet/in.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 
36     void process(BGPDUMP_ENTRY *entry);
37     void show_attr(attributes_t *attr);
38     void show_prefixes(int count,struct prefix *prefix);
39 #ifdef BGPDUMP_HAVE_IPV6
40     void show_v6_prefixes(int count, struct prefix *prefix);
41 #endif
42 
main(int argc,char ** argv)43 int main(int argc, char **argv) {
44     BGPDUMP *my_dump;
45     BGPDUMP_ENTRY *my_entry=NULL;
46 
47     if(argc>1) {
48 	my_dump=bgpdump_open_dump(argv[1]);
49     } else {
50 	my_dump=bgpdump_open_dump("dumps/updates.20020701.0032");
51     }
52 
53     if(my_dump==NULL) {
54 	printf("Error opening dump file ...\n");
55 	exit(1);
56     }
57 
58     do {
59 //fprintf(stdout, "Offset: %d\n", gztell(my_dump->f));
60 	my_entry=bgpdump_read_next(my_dump);
61 	if(my_entry!=NULL) {
62 	    process(my_entry);
63 	    bgpdump_free_mem(my_entry);
64 	}
65     } while(my_dump->eof==0);
66 
67     bgpdump_close_dump(my_dump);
68 //fprintf(stderr, "%s: OK=%d, BAD=%d (%f%% OK)\n", my_dump->filename, my_dump->parsed_ok, my_dump->parsed - my_dump->parsed_ok, (float) my_dump->parsed_ok / my_dump->parsed * 100);
69 
70  return 0;
71 }
72 
73 char *bgp_state_name[] = {
74     "Unknown",
75     "IDLE",
76     "CONNECT",
77     "ACTIVE",
78     "OPEN_SENT",
79     "OPEN_CONFIRM",
80     "ESTABLISHED",
81     NULL
82 };
83 
84 char *bgp_message_types[] = {
85     "Unknown",
86     "Open",
87     "Update/Withdraw",
88     "Notification",
89     "Keepalive"
90 };
91 
92 char *notify_codes[] = {
93     "Unknown",
94     "Message Header Error",
95     "OPEN Message Error",
96     "UPDATE Message Error",
97     "Hold Timer Expired",
98     "Finite State Machine Error",
99     "Cease"
100 };
101 
102 char *notify_subcodes[][12] = {
103     { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
104     /* Message Header Error */
105     {
106 	"None",
107  	"Connection Not Synchronized",
108 	"Bad Message Length",
109 	"Bad Message Type",
110 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
111     },
112     /* OPEN Message Error */
113     {
114 	"None",
115 	"Unsupported Version Number",
116 	"Bad Peer AS",
117 	"Bad BGP Identifier",
118 	"Unsupported Optional Parameter",
119 	"Authentication Failure",
120 	"Unacceptable Hold Time",
121 	NULL, NULL, NULL, NULL, NULL
122     },
123     /* UPDATE Message Error */
124     {
125 	"None",
126 	"Malformed Attribute List",
127 	"Unrecognized Well-known Attribute",
128 	"Missing Well-known Attribute",
129 	"Attribute Flags Error",
130 	"Attribute Length Error",
131 	"Invalid ORIGIN Attribute",
132 	"AS Routing Loop",
133 	"Invalid NEXT_HOP Attribute",
134 	"Optional Attribute Error",
135 	"Invalid Network Field",
136 	"Malformed AS_PATH"
137     },
138     /* Hold Timer Expired */
139     { "None", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
140     /* Finite State Machine Error */
141     { "None", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
142     /* Cease */
143     { "None", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
144 
145 };
146 
process(BGPDUMP_ENTRY * entry)147 void process(BGPDUMP_ENTRY *entry) {
148     char prefix[BGPDUMP_ADDRSTRLEN], peer_ip[BGPDUMP_ADDRSTRLEN];
149     char source_ip[BGPDUMP_ADDRSTRLEN], destination_ip[BGPDUMP_ADDRSTRLEN];
150     struct mp_nlri *mp_announce, *mp_withdraw;
151     int i, code, subcode;
152 	BGPDUMP_TABLE_DUMP_V2_PREFIX *e;
153 
154 if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE && entry->body.zebra_message.type == BGP_MSG_KEEPALIVE) return;
155 if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE && entry->body.zebra_message.type == BGP_MSG_OPEN) return;
156 if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE && entry->body.zebra_message.type == BGP_MSG_NOTIFY) return;
157 if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_STATE_CHANGE && entry->length == 8) return;
158 
159     printf("TIME            : %s",asctime(gmtime(&entry->time)));
160     printf("LENGTH          : %u\n", entry->length);
161     switch(entry->type) {
162 	case BGPDUMP_TYPE_MRTD_TABLE_DUMP:
163 	    if(entry->subtype == AFI_IP) {
164 		strcpy(prefix, inet_ntoa(entry->body.mrtd_table_dump.prefix.v4_addr));
165 		strcpy(peer_ip, inet_ntoa(entry->body.mrtd_table_dump.peer_ip.v4_addr));
166 #ifdef BGPDUMP_HAVE_IPV6
167 	    } else if(entry->subtype == AFI_IP6) {
168 		inet_ntop(AF_INET6, &entry->body.mrtd_table_dump.prefix.v6_addr, prefix,
169 			  sizeof(prefix));
170 		inet_ntop(AF_INET6, &entry->body.mrtd_table_dump.peer_ip.v6_addr, peer_ip,
171 			  sizeof(peer_ip));
172 #endif
173 	    } else {
174 		*prefix = '\0';
175 		*peer_ip = '\0';
176 	    }
177 	    printf("TYPE            : BGP Table Dump Entry\n");
178 	    printf("    VIEW        : %d\n",entry->body.mrtd_table_dump.view);
179 	    printf("    SEQUENCE    : %d\n",entry->body.mrtd_table_dump.sequence);
180 	    printf("    PREFIX      : %s/%d\n",prefix,entry->body.mrtd_table_dump.mask);
181 	    printf("    STATUS      : %d\n",entry->body.mrtd_table_dump.status);
182 	    printf("    UPTIME      : %s",asctime(gmtime(&entry->body.mrtd_table_dump.uptime)));
183 	    printf("    PEER IP     : %s\n",peer_ip);
184 	    printf("    PEER AS     : %u\n",entry->body.mrtd_table_dump.peer_as);
185     	show_attr(entry->attr);
186 	    break;
187 
188 	case BGPDUMP_TYPE_TABLE_DUMP_V2:
189 
190 		e = &entry->body.mrtd_table_dump_v2_prefix;
191 
192 	    if(e->afi == AFI_IP) {
193 			strcpy(prefix, inet_ntoa(e->prefix.v4_addr));
194 #ifdef BGPDUMP_HAVE_IPV6
195 	    } else if(e->afi == AFI_IP6) {
196 			inet_ntop(AF_INET6, &e->prefix.v6_addr, prefix, INET6_ADDRSTRLEN);
197 #endif
198 	    } else {
199 			printf("Error: BGP table dump version 2 entry with unknown subtype\n");
200 			break;
201 	    }
202 
203 		for(i = 0; i < e->entry_count; i++){
204 			if(i){
205     			printf("\nTIME            : %s",asctime(gmtime(&entry->time)));
206     			printf("LENGTH          : %u\n", entry->length);
207 			}
208 
209 
210     		printf("TYPE            : BGP Table Dump version 2 Entry\n");
211     		printf("    SEQUENCE    : %d\n",e->seq);
212     		printf("    PREFIX      : %s/%d\n",prefix,e->prefix_length);
213 
214 			if(e->entries[i].peer->afi == AFI_IP){
215 				inet_ntop(AF_INET, &e->entries[i].peer->peer_ip, peer_ip, INET6_ADDRSTRLEN);
216 #ifdef BGPDUMP_HAVE_IPV6
217 			} else if (e->entries[i].peer->afi == AFI_IP6){
218 				inet_ntop(AF_INET6, &e->entries[i].peer->peer_ip, peer_ip, INET6_ADDRSTRLEN);
219 #endif
220 			} else {
221 				sprintf(peer_ip, "N/A, unsupported AF");
222 			}
223     		printf("    PEER IP     : %s\n",peer_ip);
224     		printf("    PEER AS     : %u\n",e->entries[i].peer->peer_as);
225 
226    			show_attr(e->entries[i].attr);
227 		}
228 
229 	    break;
230 
231 	case BGPDUMP_TYPE_ZEBRA_BGP:
232 	    printf("TYPE            : Zebra BGP \n");
233 		if(entry->body.zebra_message.address_family == AFI_IP) {
234 		    strcpy(source_ip, inet_ntoa(entry->body.zebra_message.source_ip.v4_addr));
235 		    strcpy(destination_ip, inet_ntoa(entry->body.zebra_message.destination_ip.v4_addr));
236 #ifdef BGPDUMP_HAVE_IPV6
237 		} else if(entry->body.zebra_message.address_family == AFI_IP6) {
238 		    inet_ntop(AF_INET6, &entry->body.zebra_message.source_ip.v6_addr, source_ip,
239 			      sizeof(source_ip));
240 		    inet_ntop(AF_INET6, &entry->body.zebra_message.destination_ip.v6_addr, destination_ip,
241 			      sizeof(destination_ip));
242 #endif
243 		} else {
244 		    *source_ip = '\0';
245 		    *destination_ip = '\0';
246 		}
247 	    switch(entry->subtype) {
248 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
249 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
250 		    printf("SUBTYPE         : Zebra BGP Message");
251 		    if(entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4) {
252 		      printf(" (32-bit ASN)\n");
253 		    } else {
254 		      printf("\n");
255 		    }
256 		    printf("    SOURCE_AS   : %u\n",entry->body.zebra_message.source_as);
257 		    printf("    DEST_AS     : %u\n",entry->body.zebra_message.destination_as);
258 		    printf("    INTERFACE   : %d\n",entry->body.zebra_message.interface_index);
259 		    printf("    SOURCE_IP   : %s\n",source_ip);
260 		    printf("    DEST_IP     : %s\n",destination_ip);
261 
262 		    if(entry->body.zebra_message.type > sizeof(bgp_message_types) / sizeof(bgp_message_types[0]))
263 			printf("MESSAGE TYPE    : Unknown\n");
264 		    else
265 			printf("MESSAGE TYPE    : %s\n", bgp_message_types[entry->body.zebra_message.type]);
266 
267 		    switch(entry->body.zebra_message.type) {
268 			case BGP_MSG_UPDATE:
269 			    printf("WITHDRAW        :\n");
270 			    show_prefixes(entry->body.zebra_message.withdraw_count,entry->body.zebra_message.withdraw);
271 #ifdef BGPDUMP_HAVE_IPV6
272 			    if(entry->attr->mp_info &&
273 			       (mp_withdraw = MP_IPV6_WITHDRAW(entry->attr->mp_info)) != NULL) {
274 				show_v6_prefixes(mp_withdraw->prefix_count, mp_withdraw->nlri);
275 			    }
276 #endif
277 			    printf("ANNOUNCE        :\n");
278 			    show_prefixes(entry->body.zebra_message.announce_count,entry->body.zebra_message.announce);
279 #ifdef BGPDUMP_HAVE_IPV6
280 			    if(entry->attr->mp_info &&
281 			       (mp_announce = MP_IPV6_ANNOUNCE(entry->attr->mp_info)) != NULL) {
282 				show_v6_prefixes(mp_announce->prefix_count, mp_announce->nlri);
283 			    }
284 #endif
285 			    break;
286 			case BGP_MSG_KEEPALIVE:
287 			    /* Nothing to do */
288 			    break;
289 			case BGP_MSG_OPEN:
290 			    printf("    VERSION     : %d\n",entry->body.zebra_message.version);
291 			    printf("    MY_ASN      : %u\n",entry->body.zebra_message.my_as);
292 			    printf("    HOLD_TIME   : %d\n",entry->body.zebra_message.hold_time);
293 			    printf("    ROUTER_ID   : %s\n",inet_ntoa(entry->body.zebra_message.bgp_id));
294 			    printf("    OPTION_LEN  : %d\n",entry->body.zebra_message.opt_len);
295 			    printf("    OPTION_DATA :");
296 			    for(i = 0; i < entry->body.zebra_message.opt_len; i++) {
297 				printf(" %02x", entry->body.zebra_message.opt_data[i]);
298 			    }
299 			    printf("\n");
300 			    break;
301 			case BGP_MSG_NOTIFY:
302 			    code = entry->body.zebra_message.error_code;
303 			    subcode = entry->body.zebra_message.sub_error_code;
304 
305 			    printf("    CODE        : %d", code);
306 			    if(code >= sizeof(notify_codes) / sizeof(notify_codes[0]))
307 				printf(" (Unknown)\n");
308 			    else
309 				printf(" (%s)\n", notify_codes[code]);
310 
311 			    printf("    SUBCODE     : %d", subcode);
312 			    if(code >= sizeof(notify_codes) / sizeof(notify_codes[0]) ||
313 			       subcode >= sizeof(notify_subcodes[0]) / sizeof(notify_subcodes[0][0]) ||
314 			       notify_subcodes[code][subcode] == NULL)
315 				printf(" (Unknown)\n");
316 			    else
317 				printf(" (%s)\n", notify_subcodes[code][subcode]);
318 
319 			    printf("    DATA        :");
320 			    for(i = 0; i < entry->body.zebra_message.notify_len; i++) {
321 				printf(" %02x", entry->body.zebra_message.notify_data[i]);
322 			    }
323 			    printf("\n");
324 			    break;
325 			default:
326 			    break;
327 		    }
328 		    break;
329 
330 		case BGPDUMP_SUBTYPE_ZEBRA_BGP_STATE_CHANGE:
331 		    printf("SUBTYPE         : Zebra BGP State Change\n");
332 		    printf("    SOURCE_AS   : %u\n",entry->body.zebra_state_change.source_as);
333 		    printf("    DEST_AS     : %u\n",entry->body.zebra_state_change.destination_as);
334 		    printf("    INTERFACE   : %d\n",entry->body.zebra_state_change.interface_index);
335 		    printf("    SOURCE_IP   : %s\n",source_ip);
336 		    printf("    DEST_IP     : %s\n",destination_ip);
337 		    printf("    OLD_STATE   : %s\n",bgp_state_name[entry->body.zebra_state_change.old_state]);
338 		    printf("    NEW_STATE   : %s\n",bgp_state_name[entry->body.zebra_state_change.new_state]);
339     		show_attr(entry->attr);
340 		    break;
341 
342 		default:
343 		    printf("SUBTYPE         : Unknown %d\n", entry->subtype);
344 	    }
345     	show_attr(entry->attr);
346 	    break;
347 	default:
348 	    printf("TYPE            : Unknown %d\n", entry->type);
349     	show_attr(entry->attr);
350 
351     }
352     printf("\n");
353 }
354 
show_attr(attributes_t * attr)355 void show_attr(attributes_t *attr) {
356     int have_nexthop = 0;
357     printf("ATTRIBUTES      :\n");
358 
359     if(attr != NULL) {
360 	    printf("   ATTR_LEN     : %d\n",attr->len);
361 
362 	    if( (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGIN) ) !=0 )		printf("   ORIGIN       : %d\n",attr->origin);
363 	    else printf("   ORIGIN       : N/A\n");
364 
365 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AS_PATH) ) !=0)		printf("   ASPATH       : %s\n",attr->aspath->str);
366 	    else printf("   ASPATH       : N/A\n");
367 
368 	    printf("   NEXT_HOP     : ");
369 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP) ) !=0) {
370 		have_nexthop = 1;
371 		printf("%s", inet_ntoa(attr->nexthop));
372 	    }
373 
374 #ifdef BGPDUMP_HAVE_IPV6
375 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
376 	         MP_IPV6_ANNOUNCE(attr->mp_info) != NULL) {
377 		char addr[INET6_ADDRSTRLEN];
378 		struct mp_nlri *mp_nlri = MP_IPV6_ANNOUNCE(attr->mp_info);
379 		u_int8_t len = mp_nlri->nexthop_len;
380 
381 		if(have_nexthop)
382 		    printf(" ");
383 
384 		have_nexthop = 1;
385 		printf("%s", inet_ntop(AF_INET6, &mp_nlri->nexthop, addr, sizeof(addr)));
386 		if(len == 32)
387 		    printf(" %s", inet_ntop(AF_INET6, &mp_nlri->nexthop_local, addr, sizeof(addr)));
388 	    }
389 #endif
390 
391 	    printf(have_nexthop ? "\n" : "N/A\n");
392 
393 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) ) !=0)	printf("   MED          : %d\n",attr->med);
394 	    else printf("   MED          : N/A\n");
395 
396 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF) ) !=0)		printf("   LOCAL_PREF   : %d\n",attr->local_pref);
397 	    else printf("   LOCAL_PREF   : N/A\n");
398 
399 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE) ) !=0)	printf("   ATOMIC_AGREG : Present\n");
400 	    else printf("   ATOMIC_AGREG : N/A\n");
401 
402 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR) ) !=0)		printf("   AGGREGATOR   : %s AS%u\n",inet_ntoa(attr->aggregator_addr),attr->aggregator_as);
403 	    else printf("   AGGREGATOR   : N/A\n");
404 
405 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES) ) !=0)	printf("   COMMUNITIES  : %s\n",attr->community->str);
406 	    else printf("   COMMUNITIES  : N/A\n");
407 
408 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AS_PATH) ) !=0) {
409 		printf("   NEW_ASPATH   : %s\n",attr->new_aspath->str);
410 	    	printf("   OLD_ASPATH   : %s\n",attr->old_aspath->str);
411 	    }
412 
413 	    if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AGGREGATOR) ) !=0)	printf("   NEW_AGGREGTR : %s AS%u\n",inet_ntoa(attr->new_aggregator_addr),attr->new_aggregator_as);
414     }
415 }
416 
show_prefixes(int count,struct prefix * prefix)417 void show_prefixes(int count,struct prefix *prefix) {
418     int i;
419     for(i=0;i<count;i++)
420 	printf("      %s/%d\n",inet_ntoa(prefix[i].address.v4_addr),prefix[i].len);
421 }
422 
423 #ifdef BGPDUMP_HAVE_IPV6
show_v6_prefixes(int count,struct prefix * prefix)424 void show_v6_prefixes(int count, struct prefix *prefix) {
425     int i;
426     char str[INET6_ADDRSTRLEN];
427 
428     for(i=0;i<count;i++){
429 	inet_ntop(AF_INET6, &prefix[i].address.v6_addr, str, sizeof(str));
430 	printf("      %s/%d\n",str, prefix[i].len);
431     }
432 }
433 #endif
434