mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-24 07:16:43 +00:00
Resurrect packet visualisation
This commit is contained in:
parent
8d0e056f81
commit
3be2ed615d
@ -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);
|
||||
|
3
serval.h
3
serval.h
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
int i;
|
||||
for (i=0;i<len;i++)
|
||||
xprintf(xpf,"%02X",packet[(*ofs)++]);
|
||||
if (len<32) xprintf(xpf,"*");
|
||||
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;
|
||||
xprintf(xpf,"%sPacket version %d (0x%02x)\n",
|
||||
indent(4),version,version);
|
||||
|
||||
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,"%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;
|
||||
|
||||
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,"\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;
|
||||
}
|
||||
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;
|
||||
unsigned int encapsulation = packet[(*ofs)++];
|
||||
xprintf(xpf,"%sEncapsulation (0x%02x);",
|
||||
indent(4),encapsulation);
|
||||
switch (encapsulation){
|
||||
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));
|
||||
xprintf(xpf, " OVERLAY\n");
|
||||
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;
|
||||
}
|
||||
case 2:
|
||||
xprintf(xpf, " SINGLE\n");
|
||||
break;
|
||||
default:
|
||||
xprintf(xpf,"%sWARNING: Version is newer than I understand.\n",indent(10));
|
||||
break;
|
||||
xprintf(xpf, " UNKNOWN\n");
|
||||
// TODO dump remainder?
|
||||
return -1;
|
||||
}
|
||||
|
||||
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]);
|
||||
xprintf(xpf, "%sSender; ", indent(4));
|
||||
int ret=serval_packetvisualise_renderaddress(xpf,packet,ofs,0);
|
||||
xprintf(xpf, "\n");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x70: /* node announce */
|
||||
{
|
||||
|
||||
if (payload_flags & 2){
|
||||
if (!(payload_flags & 4)){
|
||||
xprintf(xpf, "%sBroadcast ID; 0x", indent(6));
|
||||
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]);
|
||||
for (i=0;i<8;i++)
|
||||
xprintf(xpf,"%02X",packet[(*ofs)++]);
|
||||
xprintf(xpf, "\n");
|
||||
}
|
||||
|
||||
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));
|
||||
}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;
|
||||
}
|
||||
}
|
||||
|
||||
nextframe:
|
||||
if (next_frame_ofs<0) {
|
||||
xprintf(xpf,"%sERROR: Cannot continue decoding payload due to previous error(s)\n",indent(6));
|
||||
return 1;
|
||||
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);
|
||||
}
|
||||
if (dumpRaw)
|
||||
_dump(xpf, packet, next_frame_ofs, *ofs, "%s", indent(10));
|
||||
(*ofs)=next_frame_ofs;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (payload_flags & 32){
|
||||
payload_len -= 64;
|
||||
}
|
||||
|
||||
int isDNAPacket(XPRINTF xpf, const unsigned char *packet, size_t *ofs, size_t len)
|
||||
{
|
||||
return 0;
|
||||
if (!(payload_flags & 128)){
|
||||
size_t payload_offset=0;
|
||||
unsigned int dest_port_raw=get_packed_uint32(payload_start, &payload_offset);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user