#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
#include <p_defs.h>
#include <p_ptoa.h>
#include <p_dump.h>
char line[100];
struct in_addr addr;
int main(int argc, char *argv[])
{
FILE *fh;
char *file = NULL;
int end = 0;
int head = 0;
int machine = 0;
if ( argc == 2 )
{
if ( strcmp(argv[1],"-m" ) == 0 ) { syntax(argv[0]); }
file = argv[1];
}
else if ( argc == 3 && strcmp(argv[1],"-m") == 0 )
{
machine = 1;
file = argv[2];
}
else
{
syntax(argv[0]);
}
if ( ( fh = fopen(file,"r") ) == NULL )
{
fprintf(stderr,"error opening '%s'\n",file);
return -1;
}
while(!end)
{
int len;
struct dump_msg msg;
char buffer[65536];
if ( ( len = fread(&msg, 1, sizeof(msg), fh) ) != sizeof(msg) )
{
fprintf(stderr,"EOF msg\n");
return -1;
}
#ifdef DEBUG
printf("type %u len %u timestamp %u\n",ntohs(msg.type),ntohs(msg.len),(unsigned int)ntohl(msg.ts));
#endif
if ( machine )
{
#ifdef FREEBSD
printf("%lu|",ntohl(msg.ts));
#else
printf("%u|",ntohl(msg.ts));
#endif
}
else
{
mytime((time_t)ntohl(msg.ts));
printf("%s ",line);
}
if ( ( len = fread(buffer, 1, ntohs(msg.len), fh) ) != ntohs(msg.len) )
{
fprintf(stderr,"EOF submsg read (read %u but should %u)\n",len,ntohs(msg.len));
return -1;
}
#ifdef DEBUG
{
int a;
for(a=0; a<len; a++)
{
if ( a & !(a%4) ) { printf(" "); }
if ( a & !(a%16) ) { printf("\n"); }
printf("%02x ",(uint8_t)buffer[a]);
}
printf("\n");
}
#endif
if ( ntohs(msg.type) == 0 && !head )
{
struct dump_header *header;
header = (struct dump_header*)buffer;
if ( machine )
{
#ifdef FREEBSD
printf("P|%lu|%u\n",ntohl(header->ip),ntohs(header->as));
#else
printf("P|%u|%u\n",ntohl(header->ip),ntohs(header->as));
#endif
}
else
{
addr.s_addr = header->ip;
printf("peer ip %s AS %u\n",inet_ntoa(addr),ntohs(header->as));
}
head=1;
}
else if ( ntohs(msg.type) == 1 && head )
{
if ( machine ) { printf("C\n"); }
else { printf("connected\n"); }
}
else if ( ntohs(msg.type) == 2 && head )
{
if ( machine ) { printf("D\n"); }
else { printf("disconnected\n"); }
}
else if ( ntohs(msg.type) == 3 && head )
{
if ( machine ) { printf("K\n"); }
else { printf("keepalive\n"); }
}
else if ( ntohs(msg.type) == 4 && head )
{
uint32_t prefix = 0;
int jump = 1;
struct dump_announce *announce;
struct dump_announce_aspath *aspath;
struct dump_announce_community *community;
announce = (struct dump_announce*)buffer;
memcpy(&prefix,&announce->prefix, sizeof(prefix));
prefix = ntohl(prefix);
if ( announce->mask == 0 ) { prefix = 0; }
else { prefix &= ( 0xffffffff ^ ( ( 1 << ( 32 - announce->mask ) ) - 1 ) ); }
jump += sizeof(announce);
aspath = (struct dump_announce_aspath*) (buffer+jump);
jump += 3;
jump += ntohs(aspath->len);
if ( machine )
{
printf("A|%u|%u|1|",prefix,announce->mask);
}
else
{
addr.s_addr = ntohl(prefix);
printf("prefix announce %s/%u ",inet_ntoa(addr),announce->mask);
printf("aspath: ");
}
{
int a;
for(a=0; a<(ntohs(aspath->len)/2); a++)
{
printf("%u",ntohs(aspath->data[a]));
if ( a < ((ntohs(aspath->len)/2) - 1 ) ) { printf(" "); }
}
}
community = (struct dump_announce_community*) (buffer+jump);
if ( machine ) { printf("|2|"); }
else { printf(" community: "); }
{
int a;
for(a=0; a<(ntohs(community->len)/4); a++)
{
struct community_record *com;
com = (struct community_record*)&community->data[a];
printf("%u:%u",ntohs(com->asn),ntohs(com->num));
if ( a < ((ntohs(community->len)/4) - 1) ) { printf(" "); }
}
}
printf("\n");
}
else if ( ntohs(msg.type) == 5 && head )
{
uint32_t prefix = 0;
int jump = 1;
struct dump_withdrawn *withdrawn;
withdrawn = (struct dump_withdrawn*)buffer;
memcpy(&prefix,&withdrawn->prefix, sizeof(prefix));
prefix = ntohl(prefix);
if ( withdrawn->mask == 0 ) { prefix = 0; }
else { prefix &= ( 0xffffffff ^ ( ( 1 << ( 32 - withdrawn->mask ) ) - 1 ) ); }
jump += sizeof(withdrawn);
if ( machine )
{
printf("W|%u|%u\n",prefix,withdrawn->mask);
}
else
{
addr.s_addr = ntohl(prefix);
printf("prefix withdrawn %s/%u\n",inet_ntoa(addr),withdrawn->mask);
}
}
else if ( ntohs(msg.type) == 255 && head )
{
if ( machine )
{
printf("E\n");
}
else
{
printf("eof\n");
}
end=1;
}
else
{
fprintf(stderr,"parsing error\n");
return -1;
}
}
fclose(fh);
return 0;
}
void mytime(time_t ts)
{
struct tm *tm;
tm = gmtime((time_t*)&ts);
strftime(line, sizeof(line), "%Y-%m-%d %H:%M:%S" , tm);
}
void syntax(char *prog)
{
printf("Piranha v%s.%s.%s Dump file decoder, Copyright(c) 2004 Pascal Gloor\n",P_VER_MA,P_VER_MI,P_VER_PL);
printf("syntax: %s [-m] <file>\n",prog);
printf("\n");
printf("-m for machine readable output:\n");
printf("timestamp|P|peer_ip|peer_as # begin of every file\n");
printf("timestamp|C # connected (Active -> Established)\n");
printf("timestamp|D # disconnected (Established -> Active)\n");
printf("timestamp|K # BGP Keepalive received\n");
printf("timestamp|A|network|mask|opt id|opt|opt id ...\n");
printf(" # BGP Announce\n");
printf("timestamp|W|network|mask # BGP Withdrawn\n");
printf("\n");
exit(-1);
}