/*
* TCPVIEW
*
* Author: Martin Hunt
* Networks and Distributed Computing
* Computing & Communications
* University of Washington
* Administration Building, AG-44
* Seattle, WA 98195
* Internet: martinh@cac.washington.edu
*
*
* Copyright 1992 by the University of Washington
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appears in all copies and that both the
* above copyright notice and this permission notice appear in supporting
* documentation, and that the name of the University of Washington not be
* used in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. This software is made
* available "as is", and
* THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
* WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
* NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: /usr/staff/martinh/tcpview/RCS/bgp.c,v 1.2 1993/04/22 20:11:19 martinh Exp $ (UW)";
#endif
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include "os.h"
#include "md.h"
int PrintFrames = 0;
#ifdef __STDC__
int getbyte(void);
u_short getword(void);
u_long getlword(void);
#else
int getbyte();
u_short getword();
u_long getlword();
#endif
char *msg_type[]= { "null","OPEN","UPDATE","NOTIFICATION","KEEPALIVE" };
char *origin_str[] = { "IGP","EGP","INCOMPLETE" };
void bgp_open(), bgp_update(), bgp_note(), bgp_keepalive();
void mess_err(), update_err(), open_err();
int getattributes();
void (*type_func[])() = { NULL, bgp_open, bgp_update, bgp_note, bgp_keepalive };
main(argc, argv)
int argc;
char *argv[];
{
int c, i=0;
int type;
int length;
if( argc > 1 )
if( *argv[1]=='-' && argv[1][1]=='f' )
PrintFrames=1;
sync:
/* look for 16 0xFF octets */
while( (c = getbyte()) != EOF) {
if( c == 0xFF ) {
i++;
if( i == 16 )
break;
} else
i = 0;
}
while(1) {
length = getword();
if( length < 19 || length > 4096 )
goto sync;
type = getbyte();
if( type < 1 || type > 4 )
goto sync;
(type_func[type])(length);
/* eat Marker */
for(i=0;i<16;i++)
if(getbyte()==EOF)
exit(0);
}
}
void bgp_open(length)
int length;
{
int i, min_length;
u_short asn, htime, version, auth;
long id;
version = getbyte();
if(version > 2)
min_length = 29;
else
min_length = 25;
if( length < min_length)
printf("OPEN: ERROR has a length of %d. Must be >= %d\n",length,min_length);
asn = getword();
htime = getword();
if(version > 2)
id = getlword();
auth = getbyte();
if(version > 2)
printf("OPEN: version: %d, asn=%d, htime=%d, id=%d auth=%d\n",
version,asn,htime,id,auth);
else
printf("OPEN version: %d, asn=%d, htime=%d, auth=%d\n",
version,asn,htime,auth);
if( length > min_length ) {
printf("WARNING: authentication data present\n");
/*fread(&auth_data,length-min_length,1,stdin); */
}
/* eat any excess */
for(i=min_length;i<length;i++)
if(getbyte()==EOF)
exit(0);
}
void bgp_update(length)
int length;
{
int j, tpal, nets;
long ip;
printf("UPDATE ");
tpal = getword(); /* Total Path Attributes Length */
nets = (length-21-tpal)/4;
if (nets<0 || length != nets*4+21+tpal) {
printf("INVALID FORMAT - ");
printf("length=%d TPAL=%d\n",length,tpal);
return;
}
if(getattributes(tpal))
printf("\nERROR: TPAL was incorrect length");
putchar('\n');
/* now print out networks */
j = 0;
while(nets--) {
ip = getlword();
printf("\t%s ",inet_ntoa(htonl(ip)));
if ( j++ == 4 ) {
j = 0;
putchar('\n');
}
}
putchar('\n');
}
char *e_msg[] = { "","Message Header Error","OPEN Message Error",
"UPDATE Message Error","Hold Timer Expired",
"Finite State Machine Error","Cease" };
void bgp_note(length)
int length;
{
int i, len=0;
int code, sub, data_len;
printf("NOTIFICATION: ");
code = getbyte();
sub = getbyte();
if(sub==-1 || code==-1)
exit(0);
data_len = length - 21;
if( code>0 && code <7 ) {
printf("%s: ",e_msg[code]);
switch (code) {
case 1:
mess_err(sub, data_len);
break;
case 2:
open_err(sub, data_len);
break;
case 3:
update_err(sub, data_len);
break;
default:
for(i=21;i<length;i++)
if(getbyte()==EOF)
exit(0);
}
} else
printf("Unknown Error Code (%d.%d)\n",code,sub);
}
void bgp_keepalive(length)
int length;
{
int i;
printf("KEEPALIVE\n");
if(length != 19)
printf("WARNING: KEEPALIVE message has length of %d (should be 19)\n",length);
for(i=19;i<length;i++)
if(getbyte()==EOF)
exit(0);
}
void mess_err(subtype, length)
int length, subtype;
{
int i, len=0;
switch(subtype) {
case 1:
printf("Connection Not Synchronized.\n");
break;
case 2:
printf("Bad Message Length: ");
if(length==2) {
printf("%d\n",getword());
len += 2;
} else if (length==1) {
printf("%d\n",getbyte());
len++;
} else printf("???\n");
break;
case 3:
printf("Bad Message Type: ");
if(length==2) {
printf("%d\n",getword());
len += 2;
} else if (length==1) {
printf("%d\n",getbyte());
len++;
} else printf("???\n");
break;
default:
printf("ERROR: unknown subtype\n");
}
for(i=len;i<length;i++)
if(getbyte()==EOF)
exit(0);
}
void open_err(subtype, length)
int length, subtype;
{
int i, len=0;
switch(subtype) {
case 1:
printf("Unsupported Version Number: ");
if(length==2) {
printf("largest supported = %d\n",getword());
len += 2;
} else if (length==1) {
printf("largest supported = %d\n",getbyte());
len++;
} else printf("???\n");
break;
case 2:
printf("Bad Peer AS\n");
break;
case 3:
printf("Bad BGP Identifier\n");
break;
case 4:
printf("Unsupported Authentication Code\n");
break;
case 5:
printf("Authentication Failure\n");
break;
default:
printf("ERROR: unknown subtype\n");
}
for(i=len;i<length;i++)
if(getbyte()==EOF)
exit(0);
}
char *update_error[] = { "", "Malformed Attribute List",
"Unrecognized Well-known Attribute: ",
"Missing Well-known Attribute: ",
"Attribute Flags Error: ",
"Attribute Length Error: ",
"Invalid ORIGIN Attribute: ",
"AS Routing Loop: ",
"Invalid NEXT_HOP Attribute: ",
"Optional Attribute Error: ",
"Invalid Network Field" };
void update_err(subtype, length)
int length, subtype;
{
int i;
if(subtype>0 && subtype <11) {
printf("%s",update_error[subtype]);
if(getattributes(length))
printf("\nERROR parsing subcode data");
putchar('\n');
} else {
printf("bad subtype (%d)\n",subtype);
for(i=0;i<length;i++)
if(getbyte()==EOF)
exit(0);
}
}
int getattributes(len)
int len;
{
int attr_flag, attr_type, extended;
int i, adl, origin, asn;
long ip;
while(len) {
attr_flag = getbyte();
attr_type = getbyte();
len -= 2;
putchar('(');
if(attr_flag & 128) putchar('O');
if(attr_flag & 64) putchar('T');
if(attr_flag & 32) putchar('P');
extended = attr_flag & 16;
if(extended) putchar('E');
putchar(')'); putchar(' ');
if( (attr_flag & 15) != 0 )
printf("\nWARNING: lower 4 bits of Attribute Flags Octet not zero\n");
if( extended ) {
adl = getword();
len -= 2;
} else {
adl = getbyte();
len -= 1;
}
switch(attr_type) {
case 1:
origin = getbyte();
len -= 1;
if(origin<0 || origin>2)
printf("ORIGIN: unknown ");
else
printf("ORIGIN: %s ",origin_str[origin]);
break;
case 2:
printf("ASN_PATH: ");
for(i=0;i<adl;i+=2) {
asn = getword();
printf("%d ",asn);
len -= 2;
}
break;
case 3:
ip = getlword();
len -= 4;
printf("NEXT_HOP: %s ",inet_ntoa(htonl(ip)));
break;
case 4:
printf("UNREACHABLE ");
break;
case 5:
printf("INTER-AS METRIC %d ",getword());
len -= 2;
break;
default:
printf("UNKNOWN TYPE CODE %d ",attr_type);
}
}
return(len);
}
/* some basic I/O functions */
int getbyte()
{
u_char b;
if(hexread(&b,1))
return( (int)b );
else
return( EOF );
}
u_short getword()
{
unsigned short buf;
if( hexread(&buf,2) )
return( ntohs(buf) );
else
return( EOF );
}
u_long getlword()
{
unsigned int buf;
if( hexread(&buf,4) )
return( ntohl(buf) );
else
return( EOF );
}
syntax highlighted by Code2HTML, v. 0.9.1