Resurrect packet visualisation

This commit is contained in:
Jeremy Lakeman 2013-09-02 14:54:33 +09:30
parent 8d0e056f81
commit 3be2ed615d
4 changed files with 247 additions and 453 deletions

View File

@ -824,7 +824,7 @@ overlay_broadcast_ensemble(struct network_destination *destination,
if (config.debug.packettx){
DEBUGF("Sending this packet via interface %s (len=%d)",interface->name,len);
//DEBUG_packet_visualise(NULL,bytes,len);
DEBUG_packet_visualise(NULL,bytes,len);
}
if (interface->state!=INTERFACE_STATE_UP){
@ -1088,7 +1088,7 @@ static void
logServalPacket(int level, struct __sourceloc __whence, const char *message, const unsigned char *packet, size_t len) {
struct mallocbuf mb = STRUCT_MALLOCBUF_NULL;
if (!message) message="<no message>";
if (serval_packetvisualise(XPRINTF_MALLOCBUF(&mb), message, packet, len) == -1)
if (serval_packetvisualise_xpf(XPRINTF_MALLOCBUF(&mb), message, packet, len) == -1)
WHY("serval_packetvisualise() failed");
else if (mb.buffer == NULL)
WHYF("serval_packetvisualise() output buffer missing, message=%s packet=%p len=%lu", alloca_toprint(-1, message, strlen(message)), packet, (long unsigned int)len);

View File

@ -577,7 +577,8 @@ int rhizome_server_get_fds(struct pollfd *fds,int *fdcount,int fdmax);
int rhizome_saw_voice_traffic();
int overlay_saw_mdp_containing_frame(struct overlay_frame *f, time_ms_t now);
int serval_packetvisualise(XPRINTF xpf, const char *message, const unsigned char *packet, size_t len);
int serval_packetvisualise(const char *message, const unsigned char *packet, size_t len);
int serval_packetvisualise_xpf(XPRINTF xpf, const char *message, const unsigned char *packet, size_t len);
int rhizome_fetching_get_fds(struct pollfd *fds,int *fdcount,int fdmax);
int rhizome_opendb();

View File

@ -36,7 +36,7 @@ const char *indent(int n)
int senderSet=0;
unsigned char senderAddress[32];
static void _dump(XPRINTF xpf, const unsigned char *data, size_t len, size_t ofs, const char *fmt, ...);
static void _dump(XPRINTF xpf, const unsigned char *data, size_t len, size_t ofs, const char *prefix);
#ifdef STANDALONE
@ -60,487 +60,279 @@ int main(int argc,char **argv)
int serval_packetvisualise_renderaddress(XPRINTF xpf, const unsigned char *packet, size_t *ofs, int senderP)
{
switch(packet[*ofs]) {
case 0x00: /* ourself */
if (senderSet) {
int i;
for(i=0;i<senderSet;i++) xprintf(xpf,"%02X",senderAddress[i]);
if (senderSet<32) xprintf(xpf,"*");
xprintf(xpf," <same as sender's address>");
} else {
xprintf(xpf," <WARNING: self-reference to sender's address>");
}
(*ofs)++;
break;
case 0x01: /* by index */
xprintf(xpf,"<address associated with index #%02x by sender>",
packet[(*ofs)+1]);
(*ofs)+=2;
break;
case 0x03: /* previously used address */
xprintf(xpf,"<same as previous address>");
(*ofs)++;
break;
case 0x09: /* prefix 3 bytes and assign index */
case 0x05: /* prefix 3 bytes */
{ int skip=0;
if (packet[*ofs]&8) skip=1;
(*ofs)++;
xprintf(xpf,"%02X%02X%02X* <24 bit prefix",
packet[(*ofs)],packet[(*ofs)+1],packet[(*ofs)+2]);
if (senderP) bcopy(&packet[*ofs],senderAddress,3); senderSet=3;
if (skip) xprintf(xpf," assigned index 0x%02x",packet[(*ofs)+3]);
xprintf(xpf,">");
(*ofs)+=3+skip;
}
break;
case 0x0a: /* prefix 7 bytes and assign index */
case 0x06: /* prefix 7 bytes */
{ int skip=0;
if (packet[*ofs]&8) skip=1;
(*ofs)++;
xprintf(xpf,"%02X%02X%02X%02X%02X%02X%02X* <56 bit prefix",
packet[(*ofs)],packet[(*ofs)+1],packet[(*ofs)+2],packet[(*ofs)+3],
packet[(*ofs)+4],packet[(*ofs)+5],packet[(*ofs)+6]);
if (senderP) bcopy(&packet[*ofs],senderAddress,7); senderSet=7;
if (skip) xprintf(xpf," assigned index 0x%02x",packet[(*ofs)+7]);
xprintf(xpf,">");
(*ofs)+=7+skip;
}
break;
case 0x07: /* prefix 11 bytes */
(*ofs)++;
xprintf(xpf,"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X* <88 bit prefix>",
packet[(*ofs)],packet[(*ofs)+1],packet[(*ofs)+2],packet[(*ofs)+3],
packet[(*ofs)+4],packet[(*ofs)+5],packet[(*ofs)+6],packet[(*ofs)+7],
packet[(*ofs)+8],packet[(*ofs)+9],packet[(*ofs)+10]);
if (senderP) bcopy(&packet[*ofs],senderAddress,11); senderSet=11;
(*ofs)+=11;
break;
case 0x0f: /* broadcast */
{
int i;
(*ofs)++;
xprintf(xpf,"<broadcast BPI=");
for(i=0;i<8;i++) xprintf(xpf,"%02X",packet[(*ofs)+i]);
(*ofs)+=8;
xprintf(xpf,">"); break;
}
case 0x0b: /* prefix 11 bytes and assign index */
case 0x0d: /* prefix 11 bytes and assign 2-byte index */
case 0x02: /* reserved */
case 0x04: /* reserved */
case 0x0c: /* reserved */
xprintf(xpf,"<illegal address token 0x%02x>",packet[(*ofs)]);
return -1;
break;
default:
case 0x0e: /* full address and assign 2-byte index */
case 0x08: /* full address and assign index */
{
int skip=0;
if (packet[*ofs]==0x08) { (*ofs)++; skip=1; }
else if (packet[*ofs]==0x0e) { (*ofs)++; skip=2; }
/* naturally presented 32 byte address */
{
int i;
for(i=0;i<32;i++) xprintf(xpf,"%02x",packet[(*ofs)+i]);
if (senderP) bcopy(&packet[*ofs],senderAddress,32); senderSet=32;
unsigned int len = packet[(*ofs)++];
xprintf(xpf,"(0x%02x) ",len);
switch (len){
case 0xFF:
xprintf(xpf,"<same as sender's address>");
return 0;
case 0xFE:
xprintf(xpf,"<same as previous address>");
return 0;
case 0xFD:
xprintf(xpf,"<you>");
return 0;
case 0xFC:
xprintf(xpf,"<me>");
return 0;
default:
if (len>32){
xprintf(xpf,"<illegal address token 0x%02x>",len);
return -1;
}
if (skip) {
xprintf(xpf," <literal 256 bit address, assigned index 0x");
int i;
for(i=0;i<skip;i++) xprintf(xpf,"%02x",packet[(*ofs)+skip]);
xprintf(xpf,">");
} else
xprintf(xpf," <literal 256 bit address>");
(*ofs)+=32+skip;
}
int i;
for (i=0;i<len;i++)
xprintf(xpf,"%02X",packet[(*ofs)++]);
if (len<32) xprintf(xpf,"*");
return 0;
}
return 0;
}
static unsigned int get_packed_uint32(const unsigned char *packet, size_t *ofs){
unsigned int ret=0;
int shift=0;
int byte;
do{
byte = packet[(*ofs)++];
ret |= (byte&0x7f)<<shift;
shift+=7;
}while(byte & 0x80);
return ret;
}
static const char * overlay_type(unsigned int type){
switch(type){
case 0x20:
return "SELF_ANNOUNCE_ACK";
case 0x50:
return "RHIZOME_ADVERT";
case 0x60:
return "PLEASE_EXPLAIN";
default:
return "UNKNOWN";
}
}
static const char * port_name(unsigned int port){
switch(port){
case 1:
return "KEY_MAP_REQUEST";
case 2:
return "LINK_STATE";
case 4:
return "STUN_REQUEST";
case 5:
return "STUN";
case 6:
return "PROBE";
case 7:
return "ECHO";
case 8:
return "TRACE";
case 10:
return "DNA_LOOKUP";
case 12:
return "VOMP";
case 13:
return "RHIZOME_REQUEST";
case 14:
return "RHIZOME_RESPONSE";
case 15:
return "DIRECTORY";
case 16:
return "RHIZOME_MANIFEST_REQUEST";
case 17:
return "RHIZOME_SYNC";
case 0x3f:
return "NO_REPLY";
default:
return "UNKNOWN";
}
}
int isOverlayPacket(XPRINTF xpf, const unsigned char *packet, size_t *ofs, size_t len)
{
if (packet[(*ofs)]!=0x4f) return 0;
if (packet[(*ofs)+1]!=0x10) return 0;
int version = (packet[(*ofs)+2]<<8)+packet[(*ofs)+3];
xprintf(xpf,"%sServal Overlay Mesh Packet version %d (0x%04x)\n",
indent(4),version,version);
if (version>0x001) {
xprintf(xpf,"%s ERROR: Packet version is newer than I know about.\n",indent(4));
unsigned int version = packet[(*ofs)++];
if (version > 1)
return 0;
}
(*ofs)+=4;
senderSet=0;
while((*ofs)<len)
{
int dumpRaw=0;
int next_frame_ofs=-1;
int frame_ofs=*ofs;
int frame_flags=0;
int frame_type=packet[(*ofs)++];
if ((frame_type&0xf0)==0xe0) {
frame_type=frame_type<<8;
frame_type|=packet[(*ofs)++];
frame_type&=0xfff;
} else if ((frame_type&0xf0)==0xf0) {
frame_type=frame_type<<16;
frame_type|=packet[(*ofs)++]<<8;
frame_type|=packet[(*ofs)++];
frame_type&=0xfffff;
}
frame_flags=frame_type&0xf;
frame_type&=0xfffffff0;
int ttl=packet[(*ofs)++];
int rfs=packet[*ofs];
switch(rfs) {
case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe:
rfs=250+256*(rfs-0xfa)+packet[++(*ofs)];
break;
case 0xff: rfs=(packet[(*ofs)+1]<<8)+packet[(*ofs)+2]; (*ofs)+=2;
default: /* Length is natural value of field, so nothing to do */
break;
}
(*ofs)++;
xprintf(xpf,"%sPacket version %d (0x%02x)\n",
indent(4),version,version);
xprintf(xpf,"%sOverlay Frame at offset 0x%x\n%stype identifier = 0x%x, modifier bits = 0x%x.\n",
indent(6),frame_ofs,indent(8),frame_type,frame_flags);
xprintf(xpf,"%sTime-to-live = %d (0x%02x)\n%sframe payload bytes = %d (0x%x).\n",
indent(8),ttl,ttl,indent(8),rfs,rfs);
/* Assuming that there is no compression or crypto, we just use the plain body
of the frame. */
const unsigned char *frame=&packet[*ofs];
int frame_len=rfs;
unsigned int encapsulation = packet[(*ofs)++];
xprintf(xpf,"%sEncapsulation (0x%02x);",
indent(4),encapsulation);
switch (encapsulation){
case 1:
xprintf(xpf, " OVERLAY\n");
break;
case 2:
xprintf(xpf, " SINGLE\n");
break;
default:
xprintf(xpf, " UNKNOWN\n");
// TODO dump remainder?
return -1;
}
next_frame_ofs=(*ofs)+rfs;
int cantDecodeFrame=0;
int cantDecodeRecipient=0;
int showSignature=0;
xprintf(xpf,"%sframe is ",indent(8));
switch(frame_flags&0x3) {
case 0: xprintf(xpf,"not compressed"); break;
case 1: xprintf(xpf,"gzip-compressed"); break;
case 2: xprintf(xpf,"bzip2-compressed"); break;
case 3: xprintf(xpf,"marked as compressed using illegal code 0x3");
cantDecodeFrame=1;
break;
xprintf(xpf, "%sSender; ", indent(4));
int ret=serval_packetvisualise_renderaddress(xpf,packet,ofs,0);
xprintf(xpf, "\n");
if (ret)
return ret;
unsigned int packet_flags = packet[(*ofs)++];
xprintf(xpf, "%sFlags (0x%02x);", indent(4), packet_flags);
if (packet_flags & 1)
xprintf(xpf, " UNICAST");
if (packet_flags & 2)
xprintf(xpf, " HAS_INTERFACE");
if (packet_flags & 4)
xprintf(xpf, " HAS_SEQUENCE");
xprintf(xpf, "\n");
if (packet_flags & 2)
xprintf(xpf, "%sSender Interface; 0x%02x\n", indent(4), packet[(*ofs)++]);
if (packet_flags & 4)
xprintf(xpf, "%sSequence; 0x%02x\n", indent(4), packet[(*ofs)++]);
while((*ofs)<len){
unsigned int payload_flags = packet[(*ofs)++];
xprintf(xpf, "%sFlags (0x%02x);", indent(6), payload_flags);
if (payload_flags & 1)
xprintf(xpf, " SENDER_SAME");
if (payload_flags & 2)
xprintf(xpf, " TO_BROADCAST");
if (payload_flags & 4)
xprintf(xpf, " ONE_HOP");
if (payload_flags & 16)
xprintf(xpf, " ENCRYPTED");
if (payload_flags & 32)
xprintf(xpf, " SIGNED");
if (payload_flags & 64)
xprintf(xpf, " ACK_SOON");
if (payload_flags & 128)
xprintf(xpf, " OVERLAY_TYPE");
xprintf(xpf, "\n");
if (!payload_flags & 1){
xprintf(xpf, "%sSender; ", indent(6));
int ret=serval_packetvisualise_renderaddress(xpf,packet,ofs,0);
xprintf(xpf, "\n");
if (ret)
return ret;
}
if (payload_flags & 2){
if (!(payload_flags & 4)){
xprintf(xpf, "%sBroadcast ID; 0x", indent(6));
int i;
for (i=0;i<8;i++)
xprintf(xpf,"%02X",packet[(*ofs)++]);
xprintf(xpf, "\n");
}
xprintf(xpf,"\n%sframe is ",indent(8));
switch(frame_flags&0xc) {
case 0: xprintf(xpf,"not encrypted"); break;
case 4: xprintf(xpf,"encrypted using recipients public key (SID)");
cantDecodeFrame=1; break;
case 8: xprintf(xpf,"signed using senders public signing key (SAS)");
/* This doesn't stop us displaying the frame, as the body is still en claire.
It does mean that we should present the signature block, and not
show the signature as part of the packet body. */
cantDecodeFrame=0;
showSignature=1;
break;
case 0xc: xprintf(xpf,"authcrypted (encrypted and authenticated) using CryptoBox (SID)");
cantDecodeFrame=1; break;
}else{
xprintf(xpf, "%sDestination; ", indent(6));
int ret=serval_packetvisualise_renderaddress(xpf,packet,ofs,0);
xprintf(xpf, "\n");
if (ret)
return ret;
if (!(payload_flags & 4)){
xprintf(xpf, "%sNext Hop; ", indent(6));
int ret=serval_packetvisualise_renderaddress(xpf,packet,ofs,0);
xprintf(xpf, "\n");
if (ret)
return ret;
}
xprintf(xpf,"\n");
if (!cantDecodeRecipient) {
/* Show next-hop, sender and destination addresses */
xprintf(xpf,"%sFrame next-hop address: ",indent(8));
if (serval_packetvisualise_renderaddress(xpf,packet,ofs,0))
{ xprintf(xpf,"\n%sERROR: Cannot decode remainder of frame\n",indent(8));
dumpRaw=1;
goto nextframe;
}
xprintf(xpf,"\n%sFrame destination address: ",indent(8));
if (serval_packetvisualise_renderaddress(xpf,packet,ofs,0))
{ xprintf(xpf,"\n%sERROR: Cannot decode remainder of frame\n",indent(8));
dumpRaw=1;
goto nextframe;
}
xprintf(xpf,"\n%sFrame source address: ",indent(8));
if (serval_packetvisualise_renderaddress(xpf,packet,ofs,1))
{ xprintf(xpf,"\n%sERROR: Cannot decode remainder of frame\n",indent(8));
dumpRaw=1;
goto nextframe;
}
xprintf(xpf,"\n");
xprintf(xpf,"%sFrame payload begins at offset 0x%x\n",indent(8),*ofs);
frame=&packet[*ofs];
frame_len=next_frame_ofs-(*ofs);
if (showSignature) frame_len-=64;
frame_ofs=0;
} else {
xprintf(xpf,"%sWARNING: Cannot decode frame addresses due to encryption.\n",
indent(8));
}
if (cantDecodeFrame) {
xprintf(xpf,"%sWARNING: Cannot decode compressed and/or encrypted frame.\n",indent(8));
_dump(xpf, frame, next_frame_ofs - *ofs, 0, "%s", indent(10));
}
else {
/* Decrypt and/or decompress frame */
switch(frame_type) {
case 0x10: /* self-announce */
{
unsigned long long time;
int i;
xprintf(xpf,"%sSelf-announcement\n",indent(8));
time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++];
xprintf(xpf,"%sStart time: %10lldms (0x%08llx)\n",indent(10),time,time);
time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++];
xprintf(xpf,"%sEnd time: %10lldms (0x%08llx)\n",indent(10),time,time);
xprintf(xpf,"%sSender's Interface number: %d\n",indent(10),frame[frame_ofs++]);
}
break;
case 0x20: /* self-announce ack */
{
unsigned long long time;
int i;
xprintf(xpf,"%sACK of self-announce\n",indent(8));
time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++];
xprintf(xpf,"%sStart time: %10lldms (0x%08llx)\n",indent(10),time,time);
time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++];
xprintf(xpf,"%sEnd time: %10lldms (0x%08llx)\n",indent(10),time,time);
int iface=frame[frame_ofs++];
xprintf(xpf,"%sSender Interface : %d\n",indent(10),iface);
}
break;
case 0x50: /* rhizome advertisement */
{
int i,j,k;
int rhizome_ad_frame_type=frame[0];
xprintf(xpf,"%sRhizome bundle advertisement frame, version %d\n",indent(8),rhizome_ad_frame_type);
unsigned short int http_port = 0;
i=1;
switch (rhizome_ad_frame_type) {
case 3:
case 4:
http_port = (frame[i] << 8) + frame[i+1];
i += 2;
xprintf(xpf,"%sHTTP port = %d\n", indent(8), http_port);
break;
}
switch (rhizome_ad_frame_type) {
case 2:
case 4:
xprintf(xpf,"%sBundle BAR(s) (i=%d, frame_len=%d):\n", indent(8),i,frame_len);
break;
case 1:
case 3:
/* Frame contains whole manifest(s) */
xprintf(xpf,"%sBundle Manifest(s) (i=%d, frame_len=%d):\n", indent(8),i,frame_len);
while(i<frame_len) {
/* Check for end of manifests */
if (frame[i] == 0xff) { i+=1; break; }
/* Check remaining bytes */
int manifest_len=(frame[i]<<8)+frame[i+1];
i+=2;
if (i > frame_len) {
xprintf(xpf,"%sERROR: Unexpected end of Frame -- skipping rest of frame.\n",indent(10));
break;
}
if (manifest_len>(frame_len-i)) {
xprintf(xpf,"%sERROR: Manifest extends for 0x%x bytes, but frame contains only 0x%x more bytes -- skipping rest of frame.\n",indent(10),manifest_len,frame_len-i);
_dump(xpf, frame, frame_len, 0, "%s", indent(12));
i=frame_len;
break;
}
/* find manifest self-signature block */
for(j=0;j<manifest_len;j++) if (frame[i+j]==0) { j++; break;}
xprintf(xpf,"%smanifest id @0x%x-0x%x/0x%x (len=0x%x) (from first signature block) = ",
indent(10),i,i+manifest_len-1,frame_len,manifest_len);
for(k=0;k<32;k++) xprintf(xpf,"%02X",frame[i+j+k+1+64]);
xprintf(xpf,"\n");
/* Print manifest text body */
int column=0;
xprintf(xpf,"%sManifest variables:\n",indent(12));
for(k=0;k<(j-1);k++) {
if (!column) { xprintf(xpf,"%s",indent(14)); column=14; }
switch(frame[i+k]) {
case '\r': /* ignore CR */
case '\n': /* LF */
column=0;
/* fall through */
default:
xprintf(xpf,"%c",frame[i+k]);
}
}
/* Print manifest signature blocks */
xprintf(xpf,"%sManifest signature blocks\n",indent(12));
for(;j<manifest_len;)
{
int sigType=frame[i+j];
int sigLen=(sigType&0x3f)*4+4+1;
switch(sigType) {
case 0x17: /* cryptosign signature */
xprintf(xpf,"%sNaCl CryptoSign Generated Signature\n",indent(14));
xprintf(xpf,"%sPublic key of signatory = ",indent(16));
for(k=0;k<32;k++) xprintf(xpf,"%02X",frame[i+j+1+64+k]);
xprintf(xpf,"\n");
xprintf(xpf,"%sSignature data:",indent(16));
for(k=0;k<64;k++)
{
if (!(k&0xf)) xprintf(xpf,"\n%s",indent(18-1));
xprintf(xpf," %02X",frame[i+j+1+k]);
}
xprintf(xpf,"\n");
break;
case 0:
sigLen=1;
default:
xprintf(xpf,"%sUnknown Signature Type 0x%02x\n",indent(14),frame[i+j]);
xprintf(xpf,"%sSignature data:",indent(16));
for(k=0;k<(sigLen-1);k++)
{
if (!(k&0xf)) xprintf(xpf,"\n%s",indent(18-1));
xprintf(xpf," %02X",frame[i+j+1+k]);
}
xprintf(xpf,"\n");
break;
}
j+=sigLen;
}
i+=manifest_len;
}
break;
default:
xprintf(xpf,"%sWARNING: Version is newer than I understand.\n",indent(10));
break;
}
xprintf(xpf,"%sBundle Advertisement Records (BARs):\n",indent(8));
for(;i<(frame_len-31);i+=32) {
xprintf(xpf,"%smanifest id = %02X%02X%02X%02X%02X%02X%02X%02X*\n",
indent(10),frame[i],frame[i+1],frame[i+2],frame[i+3],
frame[i+4],frame[i+5],frame[i+6],frame[i+7]);
unsigned long long manifest_version=0;
for(j=0;j<7;j++) manifest_version=(manifest_version<<8)|frame[i+8+j];
xprintf(xpf,"%smanifest revision = %lld (0x%llx)\n",
indent(12),manifest_version,manifest_version);
xprintf(xpf,"%smanifest TTL = %d (0x%x)\n",
indent(12),frame[i+16],frame[i+16]);
unsigned long long file_size=0;
for(j=0;j<6;j++) file_size=(file_size<<8)+frame[i+18+j];
xprintf(xpf,"%sassociated file size = %lld (0x%llx) bytes\n",
indent(12),file_size,file_size);
double lat0=((frame[i+24]<<8)+frame[i+25])*180/65535-90;
double long0=((frame[i+26]<<8)+frame[i+27])*360/65535-180;
double lat1=((frame[i+28]<<8)+frame[i+29])*180/65535-90;
double long1=((frame[i+30]<<8)+frame[i+31])*360/65535-180;
xprintf(xpf,"%sgeographic extent of relevance (lat,long) = (%.f,%.f) - (%.f,%.f)\n",
indent(12),lat0,long0,lat1,long1);
}
}
break;
case 0x70: /* node announce */
{
int i;
xprintf(xpf,"%sNode reachability announcment(s):\n",indent(8));
for(i=0;i<frame_len;i+=8)
xprintf(xpf,"%s %02X%02X%02X%02X%02X%02X* best link score = %d, via %d gateways\n",
indent(10),
frame[i+0],frame[i+1],frame[i+2],frame[i+3],
frame[i+4],frame[i+5],
frame[i+6],frame[i+7]);
}
break;
case 0x30: /* MDP frame */
{
int version=(frame[0]<<8)|(frame[1]);
xprintf(xpf,"%sMDP frame (version=0x%04x):\n",indent(8),version);
int src_port=(frame[2]<<24)|(frame[3]<<16)|(frame[4]<<8)|frame[5];
int dst_port=(frame[6]<<24)|(frame[7]<<16)|(frame[8]<<8)|frame[9];
xprintf(xpf,"%s source port =%-6d (0x%08x)\n",
indent(10),src_port,src_port);
xprintf(xpf,"%s destination port =%-6d (0x%08x)\n",
indent(10),dst_port,dst_port);
xprintf(xpf,"%sMDP Payload:\n",indent(10));
_dump(xpf, frame + 10, frame_len - 10, 0, "%sframe+", indent(12));
}
break;
case 0x40: /* voice frame */
case 0x60: /* please explain (request for expansion of an abbreviated address) */
default:
{
/* Reserved values */
xprintf(xpf,"%sWARNING: Packet contains reserved/unknown frame type 0x%02x\n", indent(8),frame_type);
_dump(xpf, frame, frame_len, 0, "%sframe+", indent(10));
}
break;
}
if (showSignature) {
xprintf(xpf,"%sWARNING: Signature is for display purposes, and has not been verified\n",indent(8));
xprintf(xpf,"%sFrame signature block (SAS signed):\n",indent(8));
_dump(xpf, frame + frame_len, len < 64 ? len : 64, 0, "%s" ,indent(10));
}
}
nextframe:
if (next_frame_ofs<0) {
xprintf(xpf,"%sERROR: Cannot continue decoding payload due to previous error(s)\n",indent(6));
return 1;
}
if (dumpRaw)
_dump(xpf, packet, next_frame_ofs, *ofs, "%s", indent(10));
(*ofs)=next_frame_ofs;
}
if (!(payload_flags & 4)){
unsigned int ttl_qos = packet[(*ofs)++];
xprintf(xpf, "%sTTL, QOS (0x%02x); %d, %d\n", indent(6), ttl_qos, ttl_qos & 0x1F, (ttl_qos >> 5) & 3);
}
int o_type=0;
if (payload_flags & 128){
o_type = packet[(*ofs)++];
xprintf(xpf, "%sOverlay Type (0x%02x); %s\n", indent(6), o_type, overlay_type(o_type));
}
if (version >=1){
xprintf(xpf, "%sMDP Sequence; 0x%02x\n", indent(6), packet[(*ofs)++]);
}
int payload_len = 0;
if (encapsulation==1){
payload_len=packet[(*ofs)++]<<8;
payload_len|=packet[(*ofs)++];
xprintf(xpf, "%sPayload length; 0x%04x\n", indent(6), payload_len);
if (payload_len > len - *ofs)
return -1;
}else{
payload_len = len - *ofs;
}
const unsigned char *payload_start = &packet[*ofs];
(*ofs)+=payload_len;
if (payload_flags & 16){
xprintf(xpf, "%sPayload unreadable due to encryption\n", indent(8));
continue;
}
if (payload_flags & 32){
payload_len -= 64;
}
if (!(payload_flags & 128)){
size_t payload_offset=0;
unsigned int dest_port_raw=get_packed_uint32(payload_start, &payload_offset);
return 1;
}
int same = dest_port_raw&1;
unsigned int dest_port = dest_port_raw >> 1;
xprintf(xpf, "%sDestination Port (0x%04x); %d %s\n", indent(8), dest_port_raw, dest_port, port_name(dest_port));
if (same){
xprintf(xpf, "%sSource Port; SAME\n", indent(8));
}else{
unsigned int src_port = get_packed_uint32(payload_start, &payload_offset);
xprintf(xpf, "%sSource Port; %d %s\n", indent(8), src_port, port_name(src_port));
}
payload_start += payload_offset;
payload_len -= payload_offset;
}
xprintf(xpf, "%sPayload body;\n", indent(8));
_dump(xpf, payload_start, payload_len, 0, indent(10));
if (payload_flags & 32){
xprintf(xpf, "%sSignature;\n", indent(8));
_dump(xpf, payload_start+payload_len, 64, 0, indent(10));
}
}
int isDNAPacket(XPRINTF xpf, const unsigned char *packet, size_t *ofs, size_t len)
{
return 0;
return 1;
}
int serval_packetvisualise_xpf(XPRINTF xpf, const char *message, const unsigned char *packet, size_t len)
{
if (message)
xprintf(xpf, "%s: ",message);
xprintf(xpf,"Packet body of %d (0x%x) bytes:\n",len,len);
xprintf(xpf,"Packet body of %d (0x%x) bytes:\n",(int)len,(int)len);
_dump(xpf, packet, len, 0, " ");
size_t ofs=0;
xprintf(xpf," Packet Structure:\n");
if (isOverlayPacket(xpf,packet,&ofs,len))
;
else if (isDNAPacket(xpf,packet,&ofs,len))
;
else {
/* Unknown packet type. */
}
if (ofs<len) {
xprintf(xpf," WARNING: The last %d (0x%x) bytes of the packet were not parsed.\n",len-ofs,len-ofs);
_dump(xpf, packet, len, ofs, " ");
xprintf(xpf," WARNING: The last %d (0x%x) bytes of the packet were not parsed.\n",(int)(len-ofs),(int)(len-ofs));
}
return 0;
}
static void _dump(XPRINTF xpf, const unsigned char *data, size_t len, size_t ofs, const char *fmt, ...)
static void _dump(XPRINTF xpf, const unsigned char *data, size_t len, size_t ofs, const char *prefix)
{
va_list ap;
va_start(ap, fmt);
int i, j;
for (i = (ofs / 16) * 16; i < len; i += 16) {
vxprintf(xpf, fmt, ap);
xprintf(xpf, "%04x:", i);
for (i = ofs & 0xFFFFFFF0; i < len; i += 16) {
xprintf(xpf, "%s%04x:", prefix, i);
for (j = 0; j < 16; ++j)
if (i + j >= ofs && i + j < len)
xprintf(xpf," %02x", data[i+j]);
@ -551,7 +343,6 @@ static void _dump(XPRINTF xpf, const unsigned char *data, size_t len, size_t ofs
xputc(i + j < ofs ? ' ' : data[i+j] >= ' ' && data[i+j] < 0x7c ? data[i+j] : '.', xpf);
xputc('\n', xpf);
}
va_end(ap);
}
int serval_packetvisualise(const char *message, const unsigned char *packet, size_t len)

View File

@ -72,7 +72,9 @@ typedef struct _xprintf {
#define _XPRINTF(F,C) ((XPRINTF){(F),(C)})
void xprintf(XPRINTF xpf, const char *fmt, ...);
void xprintf(XPRINTF xpf, const char *fmt, ...)
__attribute__ (( format(printf,2,3) ));
;
void vxprintf(XPRINTF xpf, const char *fmt, va_list);
void xputs(const char *str, XPRINTF xpf);
void xputc(char c, XPRINTF xpf);