/* Serval Mesh Copyright (C) 2010-2012 Paul Gardner-Stephen Copyright (C) 2010-2012 Serval Project Pty Limited Copyright (C) 2012 Serval Project Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #define MAX_SPACES 120 char *spaces=" "" "" "" " " "" "" "" " " "" "" "" "; char *indent(int n) { return &spaces[MAX_SPACES-n]; } int senderSet=0; unsigned char senderAddress[32]; #ifdef STANDALONE int main(int argc,char **argv) { int i,n; int len; unsigned char buff[8192]; for(n=0;n<1024;n++) { int i; len=random()%8192; for(i=0;i"); } else { fprintf(f," "); } (*ofs)++; break; case 0x01: /* by index */ fprintf(f,"
", packet[(*ofs)+1]); (*ofs)+=2; break; case 0x03: /* previously used address */ fprintf(f,""); (*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)++; fprintf(f,"%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) fprintf(f," assigned index 0x%02x",packet[(*ofs)+3]); fprintf(f,">"); (*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)++; fprintf(f,"%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) fprintf(f," assigned index 0x%02x",packet[(*ofs)+7]); fprintf(f,">"); (*ofs)+=7+skip; } break; case 0x07: /* prefix 11 bytes */ (*ofs)++; fprintf(f,"%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)++; fprintf(f,""); 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 */ fprintf(f,"",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++) fprintf(f,"%02x",packet[(*ofs)+i]); if (senderP) bcopy(&packet[*ofs],senderAddress,32); senderSet=32; } if (skip) { fprintf(f," "); } else fprintf(f," "); (*ofs)+=32+skip; } } return 0; } int isOverlayPacket(FILE *f, 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]; fprintf(f,"%sServal Overlay Mesh Packet version %d (0x%04x)\n", indent(4),version,version); if (version>0x001) { fprintf(f,"%s WARNING: Packet version is newer than I know about.\n",indent(4)); } (*ofs)+=4; senderSet=0; while((*ofs)=' ' &&frame[i+j]<0x7c?frame[i+j]:'.'); fprintf(f,"\n"); } } else { /* Decrypt and/or decompress frame */ switch(frame_type) { case 0x10: /* self-announce */ { unsigned long long time; int i; fprintf(f,"%sSelf-announcement\n",indent(8)); time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++]; fprintf(f,"%sStart time: %10lldms (0x%08llx)\n",indent(10),time,time); time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++]; fprintf(f,"%sEnd time: %10lldms (0x%08llx)\n",indent(10),time,time); fprintf(f,"%sSender's Interface number: %d\n",indent(10),frame[frame_ofs++]); } break; case 0x20: /* self-announce ack */ { unsigned long long time; int i; fprintf(f,"%sACK of self-announce\n",indent(8)); time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++]; fprintf(f,"%sStart time: %10lldms (0x%08llx)\n",indent(10),time,time); time=0; for(i=0;i<4;i++) time=(time<<8)|frame[frame_ofs++]; fprintf(f,"%sEnd time: %10lldms (0x%08llx)\n",indent(10),time,time); int iface=frame[frame_ofs++]; fprintf(f,"%sSender Interface : %d\n",indent(10),iface); } break; case 0x50: /* rhizome advertisement */ { int i,j,k; int rhizome_ad_frame_type=frame[0]; fprintf(f,"%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; fprintf(f,"%sHTTP port = %d\n", indent(8), http_port); break; } switch (rhizome_ad_frame_type) { case 2: case 4: fprintf(f,"%sBundle BAR(s) (i=%d, frame_len=%d):\n", indent(8),i,frame_len); break; case 1: case 3: /* Frame contains whole manifest(s) */ fprintf(f,"%sBundle Manifest(s) (i=%d, frame_len=%d):\n", indent(8),i,frame_len); while(i frame_len) { fprintf(f,"%sERROR: Unexpected end of Frame -- skipping rest of frame.\n",indent(10)); break; } if (manifest_len>(frame_len-i)) { fprintf(f,"%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); int j; for(;i=' ' &&frame[i+j]<0x7c?frame[i+j]:'.'); fprintf(f,"\n"); } i=frame_len; break; } /* find manifest self-signature block */ for(j=0;j=' ' &&frame[i+j]<0x7c?frame[i+j+10]:'.'); fprintf(f,"\n"); } } break; case 0x40: /* voice frame */ case 0x60: /* please explain (request for expansion of an abbreviated address) */ default: { /* Reserved values */ fprintf(f,"%sWARNING: Packet contains reserved/unknown frame type 0x%02x\n", indent(8),frame_type); int i,j; for(i=0;i=' ' &&frame[i+j]<0x7c?frame[i+j]:'.'); fprintf(f,"\n"); } } break; } if (showSignature) { int i,j; fprintf(f,"%sWARNING: Signature is for display purposes, and has not been verified\n",indent(8)); fprintf(f,"%sFrame signature block (SAS signed):\n",indent(8)); for(i=0;i<64;i+=16) { fprintf(f,"%s%04x :",indent(10),i); for(j=0;j<16&&(i+j)=' ' &&frame[frame_len+i+j]<0x7c?frame[frame_len+i+j]:'.'); fprintf(f,"\n"); } } } nextframe: if (next_frame_ofs<0) { fprintf(f,"%sERROR: Cannot continue decoding payload due to previous error(s)\n",indent(6)); return 1; } if (dumpRaw) { int i,j; for(i=0;i=(*ofs)) { fprintf(f,"%s%04x :",indent(10),i); for(j=0;j<16&&(i+j)=' ' &&packet[i+j]<0x7c?packet[i+j]:'.'); fprintf(f,"\n"); } } (*ofs)=next_frame_ofs; continue; } return 1; } int isDNAPacket(FILE *f, const unsigned char *packet, size_t *ofs, size_t len) { return 0; } int serval_packetvisualise(FILE *f, const char *message, const unsigned char *packet, size_t len) { if (f == NULL) return -1; if (message) fprintf(f,"%s:\n",message); int i,j; fprintf(f," Packet body of %d (0x%x) bytes:\n",len,len); for(i=0;i=' ' &&packet[i+j]<0x7c?packet[i+j]:'.'); fprintf(f,"\n"); } size_t ofs=0; fprintf(f," Packet Structure:\n"); if (isOverlayPacket(f,packet,&ofs,len)) ; else if (isDNAPacket(f,packet,&ofs,len)) ; else { /* Unknown packet type. */ } if (ofs=ofs) { fprintf(f," %04x :",i); for(j=0;j<16&&(i+j)=' ' &&packet[i+j]<0x7c?packet[i+j]:'.'); fprintf(f,"\n"); } } return 0; }