example.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. Copyright (c) 2007 - 2010 RIPE NCC - All Rights Reserved
  3. Permission to use, copy, modify, and distribute this software and its
  4. documentation for any purpose and without fee is hereby granted, provided
  5. that the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation, and that the name of the author not be used in advertising or
  8. publicity pertaining to distribution of the software without specific,
  9. written prior permission.
  10. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  11. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  12. AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  13. DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  14. AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. Parts of this code have been engineered after analiyzing GNU Zebra's
  17. source code and therefore might contain declarations/code from GNU
  18. Zebra, Copyright (C) 1999 Kunihiro Ishiguro. Zebra is a free routing
  19. software, distributed under the GNU General Public License. A copy of
  20. this license is included with libbgpdump.
  21. Author: Dan Ardelean (dan@ripe.net)
  22. */
  23. #include "bgpdump_lib.h"
  24. #include <time.h>
  25. #include <stdlib.h>
  26. #include <netinet/in.h>
  27. #include <sys/socket.h>
  28. #include <arpa/inet.h>
  29. void process(BGPDUMP_ENTRY *entry);
  30. void show_attr(attributes_t *attr);
  31. void show_prefixes(int count,struct prefix *prefix);
  32. #ifdef BGPDUMP_HAVE_IPV6
  33. void show_v6_prefixes(int count, struct prefix *prefix);
  34. #endif
  35. int main(int argc, char **argv) {
  36. BGPDUMP *my_dump;
  37. BGPDUMP_ENTRY *my_entry=NULL;
  38. if(argc>1) {
  39. my_dump=bgpdump_open_dump(argv[1]);
  40. } else {
  41. my_dump=bgpdump_open_dump("dumps/updates.20020701.0032");
  42. }
  43. if(my_dump==NULL) {
  44. printf("Error opening dump file ...\n");
  45. exit(1);
  46. }
  47. do {
  48. //fprintf(stdout, "Offset: %d\n", gztell(my_dump->f));
  49. my_entry=bgpdump_read_next(my_dump);
  50. if(my_entry!=NULL) {
  51. process(my_entry);
  52. bgpdump_free_mem(my_entry);
  53. }
  54. } while(my_dump->eof==0);
  55. bgpdump_close_dump(my_dump);
  56. //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);
  57. return 0;
  58. }
  59. char *bgp_state_name[] = {
  60. "Unknown",
  61. "IDLE",
  62. "CONNECT",
  63. "ACTIVE",
  64. "OPEN_SENT",
  65. "OPEN_CONFIRM",
  66. "ESTABLISHED",
  67. NULL
  68. };
  69. char *bgp_message_types[] = {
  70. "Unknown",
  71. "Open",
  72. "Update/Withdraw",
  73. "Notification",
  74. "Keepalive"
  75. };
  76. char *notify_codes[] = {
  77. "Unknown",
  78. "Message Header Error",
  79. "OPEN Message Error",
  80. "UPDATE Message Error",
  81. "Hold Timer Expired",
  82. "Finite State Machine Error",
  83. "Cease"
  84. };
  85. char *notify_subcodes[][12] = {
  86. { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
  87. /* Message Header Error */
  88. {
  89. "None",
  90. "Connection Not Synchronized",
  91. "Bad Message Length",
  92. "Bad Message Type",
  93. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  94. },
  95. /* OPEN Message Error */
  96. {
  97. "None",
  98. "Unsupported Version Number",
  99. "Bad Peer AS",
  100. "Bad BGP Identifier",
  101. "Unsupported Optional Parameter",
  102. "Authentication Failure",
  103. "Unacceptable Hold Time",
  104. NULL, NULL, NULL, NULL, NULL
  105. },
  106. /* UPDATE Message Error */
  107. {
  108. "None",
  109. "Malformed Attribute List",
  110. "Unrecognized Well-known Attribute",
  111. "Missing Well-known Attribute",
  112. "Attribute Flags Error",
  113. "Attribute Length Error",
  114. "Invalid ORIGIN Attribute",
  115. "AS Routing Loop",
  116. "Invalid NEXT_HOP Attribute",
  117. "Optional Attribute Error",
  118. "Invalid Network Field",
  119. "Malformed AS_PATH"
  120. },
  121. /* Hold Timer Expired */
  122. { "None", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
  123. /* Finite State Machine Error */
  124. { "None", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
  125. /* Cease */
  126. { "None", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
  127. };
  128. void process(BGPDUMP_ENTRY *entry) {
  129. char prefix[BGPDUMP_ADDRSTRLEN], peer_ip[BGPDUMP_ADDRSTRLEN];
  130. char source_ip[BGPDUMP_ADDRSTRLEN], destination_ip[BGPDUMP_ADDRSTRLEN];
  131. struct mp_nlri *mp_announce, *mp_withdraw;
  132. int i, code, subcode;
  133. BGPDUMP_TABLE_DUMP_V2_PREFIX *e;
  134. if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE && entry->body.zebra_message.type == BGP_MSG_KEEPALIVE) return;
  135. if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE && entry->body.zebra_message.type == BGP_MSG_OPEN) return;
  136. if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE && entry->body.zebra_message.type == BGP_MSG_NOTIFY) return;
  137. if(entry->type == BGPDUMP_TYPE_ZEBRA_BGP && entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_STATE_CHANGE && entry->length == 8) return;
  138. printf("TIME : %s",asctime(gmtime(&entry->time)));
  139. printf("LENGTH : %u\n", entry->length);
  140. switch(entry->type) {
  141. case BGPDUMP_TYPE_MRTD_TABLE_DUMP:
  142. if(entry->subtype == AFI_IP) {
  143. strcpy(prefix, inet_ntoa(entry->body.mrtd_table_dump.prefix.v4_addr));
  144. strcpy(peer_ip, inet_ntoa(entry->body.mrtd_table_dump.peer_ip.v4_addr));
  145. #ifdef BGPDUMP_HAVE_IPV6
  146. } else if(entry->subtype == AFI_IP6) {
  147. inet_ntop(AF_INET6, &entry->body.mrtd_table_dump.prefix.v6_addr, prefix,
  148. sizeof(prefix));
  149. inet_ntop(AF_INET6, &entry->body.mrtd_table_dump.peer_ip.v6_addr, peer_ip,
  150. sizeof(peer_ip));
  151. #endif
  152. } else {
  153. *prefix = '\0';
  154. *peer_ip = '\0';
  155. }
  156. printf("TYPE : BGP Table Dump Entry\n");
  157. printf(" VIEW : %d\n",entry->body.mrtd_table_dump.view);
  158. printf(" SEQUENCE : %d\n",entry->body.mrtd_table_dump.sequence);
  159. printf(" PREFIX : %s/%d\n",prefix,entry->body.mrtd_table_dump.mask);
  160. printf(" STATUS : %d\n",entry->body.mrtd_table_dump.status);
  161. printf(" UPTIME : %s",asctime(gmtime(&entry->body.mrtd_table_dump.uptime)));
  162. printf(" PEER IP : %s\n",peer_ip);
  163. printf(" PEER AS : %u\n",entry->body.mrtd_table_dump.peer_as);
  164. show_attr(entry->attr);
  165. break;
  166. case BGPDUMP_TYPE_TABLE_DUMP_V2:
  167. e = &entry->body.mrtd_table_dump_v2_prefix;
  168. if(e->afi == AFI_IP) {
  169. strcpy(prefix, inet_ntoa(e->prefix.v4_addr));
  170. #ifdef BGPDUMP_HAVE_IPV6
  171. } else if(e->afi == AFI_IP6) {
  172. inet_ntop(AF_INET6, &e->prefix.v6_addr, prefix, INET6_ADDRSTRLEN);
  173. #endif
  174. } else {
  175. printf("Error: BGP table dump version 2 entry with unknown subtype\n");
  176. break;
  177. }
  178. for(i = 0; i < e->entry_count; i++){
  179. if(i){
  180. printf("\nTIME : %s",asctime(gmtime(&entry->time)));
  181. printf("LENGTH : %u\n", entry->length);
  182. }
  183. printf("TYPE : BGP Table Dump version 2 Entry\n");
  184. printf(" SEQUENCE : %d\n",e->seq);
  185. printf(" PREFIX : %s/%d\n",prefix,e->prefix_length);
  186. if(e->entries[i].peer->afi == AFI_IP){
  187. inet_ntop(AF_INET, &e->entries[i].peer->peer_ip, peer_ip, INET6_ADDRSTRLEN);
  188. #ifdef BGPDUMP_HAVE_IPV6
  189. } else if (e->entries[i].peer->afi == AFI_IP6){
  190. inet_ntop(AF_INET6, &e->entries[i].peer->peer_ip, peer_ip, INET6_ADDRSTRLEN);
  191. #endif
  192. } else {
  193. sprintf(peer_ip, "N/A, unsupported AF");
  194. }
  195. printf(" PEER IP : %s\n",peer_ip);
  196. printf(" PEER AS : %u\n",e->entries[i].peer->peer_as);
  197. show_attr(e->entries[i].attr);
  198. }
  199. break;
  200. case BGPDUMP_TYPE_ZEBRA_BGP:
  201. printf("TYPE : Zebra BGP \n");
  202. if(entry->body.zebra_message.address_family == AFI_IP) {
  203. strcpy(source_ip, inet_ntoa(entry->body.zebra_message.source_ip.v4_addr));
  204. strcpy(destination_ip, inet_ntoa(entry->body.zebra_message.destination_ip.v4_addr));
  205. #ifdef BGPDUMP_HAVE_IPV6
  206. } else if(entry->body.zebra_message.address_family == AFI_IP6) {
  207. inet_ntop(AF_INET6, &entry->body.zebra_message.source_ip.v6_addr, source_ip,
  208. sizeof(source_ip));
  209. inet_ntop(AF_INET6, &entry->body.zebra_message.destination_ip.v6_addr, destination_ip,
  210. sizeof(destination_ip));
  211. #endif
  212. } else {
  213. *source_ip = '\0';
  214. *destination_ip = '\0';
  215. }
  216. switch(entry->subtype) {
  217. case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE:
  218. case BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4:
  219. printf("SUBTYPE : Zebra BGP Message");
  220. if(entry->subtype == BGPDUMP_SUBTYPE_ZEBRA_BGP_MESSAGE_AS4) {
  221. printf(" (32-bit ASN)\n");
  222. } else {
  223. printf("\n");
  224. }
  225. printf(" SOURCE_AS : %u\n",entry->body.zebra_message.source_as);
  226. printf(" DEST_AS : %u\n",entry->body.zebra_message.destination_as);
  227. printf(" INTERFACE : %d\n",entry->body.zebra_message.interface_index);
  228. printf(" SOURCE_IP : %s\n",source_ip);
  229. printf(" DEST_IP : %s\n",destination_ip);
  230. if(entry->body.zebra_message.type > sizeof(bgp_message_types) / sizeof(bgp_message_types[0]))
  231. printf("MESSAGE TYPE : Unknown\n");
  232. else
  233. printf("MESSAGE TYPE : %s\n", bgp_message_types[entry->body.zebra_message.type]);
  234. switch(entry->body.zebra_message.type) {
  235. case BGP_MSG_UPDATE:
  236. printf("WITHDRAW :\n");
  237. show_prefixes(entry->body.zebra_message.withdraw_count,entry->body.zebra_message.withdraw);
  238. #ifdef BGPDUMP_HAVE_IPV6
  239. if(entry->attr->mp_info &&
  240. (mp_withdraw = MP_IPV6_WITHDRAW(entry->attr->mp_info)) != NULL) {
  241. show_v6_prefixes(mp_withdraw->prefix_count, mp_withdraw->nlri);
  242. }
  243. #endif
  244. printf("ANNOUNCE :\n");
  245. show_prefixes(entry->body.zebra_message.announce_count,entry->body.zebra_message.announce);
  246. #ifdef BGPDUMP_HAVE_IPV6
  247. if(entry->attr->mp_info &&
  248. (mp_announce = MP_IPV6_ANNOUNCE(entry->attr->mp_info)) != NULL) {
  249. show_v6_prefixes(mp_announce->prefix_count, mp_announce->nlri);
  250. }
  251. #endif
  252. break;
  253. case BGP_MSG_KEEPALIVE:
  254. /* Nothing to do */
  255. break;
  256. case BGP_MSG_OPEN:
  257. printf(" VERSION : %d\n",entry->body.zebra_message.version);
  258. printf(" MY_ASN : %u\n",entry->body.zebra_message.my_as);
  259. printf(" HOLD_TIME : %d\n",entry->body.zebra_message.hold_time);
  260. printf(" ROUTER_ID : %s\n",inet_ntoa(entry->body.zebra_message.bgp_id));
  261. printf(" OPTION_LEN : %d\n",entry->body.zebra_message.opt_len);
  262. printf(" OPTION_DATA :");
  263. for(i = 0; i < entry->body.zebra_message.opt_len; i++) {
  264. printf(" %02x", entry->body.zebra_message.opt_data[i]);
  265. }
  266. printf("\n");
  267. break;
  268. case BGP_MSG_NOTIFY:
  269. code = entry->body.zebra_message.error_code;
  270. subcode = entry->body.zebra_message.sub_error_code;
  271. printf(" CODE : %d", code);
  272. if(code >= sizeof(notify_codes) / sizeof(notify_codes[0]))
  273. printf(" (Unknown)\n");
  274. else
  275. printf(" (%s)\n", notify_codes[code]);
  276. printf(" SUBCODE : %d", subcode);
  277. if(code >= sizeof(notify_codes) / sizeof(notify_codes[0]) ||
  278. subcode >= sizeof(notify_subcodes[0]) / sizeof(notify_subcodes[0][0]) ||
  279. notify_subcodes[code][subcode] == NULL)
  280. printf(" (Unknown)\n");
  281. else
  282. printf(" (%s)\n", notify_subcodes[code][subcode]);
  283. printf(" DATA :");
  284. for(i = 0; i < entry->body.zebra_message.notify_len; i++) {
  285. printf(" %02x", entry->body.zebra_message.notify_data[i]);
  286. }
  287. printf("\n");
  288. break;
  289. default:
  290. break;
  291. }
  292. break;
  293. case BGPDUMP_SUBTYPE_ZEBRA_BGP_STATE_CHANGE:
  294. printf("SUBTYPE : Zebra BGP State Change\n");
  295. printf(" SOURCE_AS : %u\n",entry->body.zebra_state_change.source_as);
  296. printf(" DEST_AS : %u\n",entry->body.zebra_state_change.destination_as);
  297. printf(" INTERFACE : %d\n",entry->body.zebra_state_change.interface_index);
  298. printf(" SOURCE_IP : %s\n",source_ip);
  299. printf(" DEST_IP : %s\n",destination_ip);
  300. printf(" OLD_STATE : %s\n",bgp_state_name[entry->body.zebra_state_change.old_state]);
  301. printf(" NEW_STATE : %s\n",bgp_state_name[entry->body.zebra_state_change.new_state]);
  302. show_attr(entry->attr);
  303. break;
  304. default:
  305. printf("SUBTYPE : Unknown %d\n", entry->subtype);
  306. }
  307. show_attr(entry->attr);
  308. break;
  309. default:
  310. printf("TYPE : Unknown %d\n", entry->type);
  311. show_attr(entry->attr);
  312. }
  313. printf("\n");
  314. }
  315. void show_attr(attributes_t *attr) {
  316. int have_nexthop = 0;
  317. printf("ATTRIBUTES :\n");
  318. if(attr != NULL) {
  319. printf(" ATTR_LEN : %d\n",attr->len);
  320. if( (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGIN) ) !=0 ) printf(" ORIGIN : %d\n",attr->origin);
  321. else printf(" ORIGIN : N/A\n");
  322. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AS_PATH) ) !=0) printf(" ASPATH : %s\n",attr->aspath->str);
  323. else printf(" ASPATH : N/A\n");
  324. printf(" NEXT_HOP : ");
  325. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP) ) !=0) {
  326. have_nexthop = 1;
  327. printf("%s", inet_ntoa(attr->nexthop));
  328. }
  329. #ifdef BGPDUMP_HAVE_IPV6
  330. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) &&
  331. MP_IPV6_ANNOUNCE(attr->mp_info) != NULL) {
  332. char addr[INET6_ADDRSTRLEN];
  333. struct mp_nlri *mp_nlri = MP_IPV6_ANNOUNCE(attr->mp_info);
  334. u_int8_t len = mp_nlri->nexthop_len;
  335. if(have_nexthop)
  336. printf(" ");
  337. have_nexthop = 1;
  338. printf("%s", inet_ntop(AF_INET6, &mp_nlri->nexthop, addr, sizeof(addr)));
  339. if(len == 32)
  340. printf(" %s", inet_ntop(AF_INET6, &mp_nlri->nexthop_local, addr, sizeof(addr)));
  341. }
  342. #endif
  343. printf(have_nexthop ? "\n" : "N/A\n");
  344. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) ) !=0) printf(" MED : %d\n",attr->med);
  345. else printf(" MED : N/A\n");
  346. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF) ) !=0) printf(" LOCAL_PREF : %d\n",attr->local_pref);
  347. else printf(" LOCAL_PREF : N/A\n");
  348. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE) ) !=0) printf(" ATOMIC_AGREG : Present\n");
  349. else printf(" ATOMIC_AGREG : N/A\n");
  350. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR) ) !=0) printf(" AGGREGATOR : %s AS%u\n",inet_ntoa(attr->aggregator_addr),attr->aggregator_as);
  351. else printf(" AGGREGATOR : N/A\n");
  352. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES) ) !=0) printf(" COMMUNITIES : %s\n",attr->community->str);
  353. else printf(" COMMUNITIES : N/A\n");
  354. if( (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEW_AS_PATH) ) !=0) {
  355. printf(" NEW_ASPATH : %s\n",attr->new_aspath->str);
  356. printf(" OLD_ASPATH : %s\n",attr->old_aspath->str);
  357. }
  358. 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);
  359. }
  360. }
  361. void show_prefixes(int count,struct prefix *prefix) {
  362. int i;
  363. for(i=0;i<count;i++)
  364. printf(" %s/%d\n",inet_ntoa(prefix[i].address.v4_addr),prefix[i].len);
  365. }
  366. #ifdef BGPDUMP_HAVE_IPV6
  367. void show_v6_prefixes(int count, struct prefix *prefix) {
  368. int i;
  369. char str[INET6_ADDRSTRLEN];
  370. for(i=0;i<count;i++){
  371. inet_ntop(AF_INET6, &prefix[i].address.v6_addr, str, sizeof(str));
  372. printf(" %s/%d\n",str, prefix[i].len);
  373. }
  374. }
  375. #endif