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