diff --git a/Makefile b/Makefile index 03281344..f5dc6733 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \ - hlrdata.o srandomdev.o simulate.o batman.o overlay.o + hlrdata.o srandomdev.o simulate.o batman.o overlay.o export.o HDRS= Makefile mphlr.h LDFLAGS= DEFS= -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DHAVE_LIBC=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDIO_H=1 -DHAVE_ERRNO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRINGS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_POLL_H=1 -DHAVE_NETDB_H=1 diff --git a/Makefile.in b/Makefile.in index 9f94d0cc..20b77036 100755 --- a/Makefile.in +++ b/Makefile.in @@ -1,5 +1,5 @@ OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \ - hlrdata.o srandomdev.o simulate.o batman.o overlay.o + hlrdata.o srandomdev.o simulate.o batman.o overlay.o export.o HDRS= Makefile mphlr.h LDFLAGS= @LDFLAGS@ DEFS= @DEFS@ diff --git a/dna.c b/dna.c index 147999de..65104546 100755 --- a/dna.c +++ b/dna.c @@ -18,9 +18,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "mphlr.h" +#include + +char *gatewayuri=NULL; char *outputtemplate=NULL; char *instrumentation_file=NULL; +char *importFile=NULL; int debug=0; int timeout=3000; /* 3000ms request timeout */ @@ -112,12 +116,23 @@ int dumpResponses(struct response_set *responses) return 0; } -int setReason(char *msg) +int setReason(char *fmt, ...) { + va_list ap,ap2; + char msg[8192]; + + va_start(ap,fmt); + va_copy(ap2,ap); + + vsnprintf(msg,8192,fmt,ap2); msg[8191]=0; + + va_end(ap); + fprintf(stderr,"Error: %s\n",msg); return -1; } + int hexvalue(unsigned char c) { if (c>='0'&&c<='9') return c-'0'; @@ -200,7 +215,7 @@ int usage(char *complaint) { fprintf(stderr,"dna: %s\n",complaint); fprintf(stderr,"usage:\n"); - fprintf(stderr," dna [-v ...] -S [-f HLR backing file]\n"); + fprintf(stderr," dna [-v ...] -S [-f HLR backing file] [-I import.txt] [-G SIP gateway]\n"); fprintf(stderr,"or\n"); fprintf(stderr," dna <-d|-s> id -A\n"); fprintf(stderr,"or\n"); @@ -211,6 +226,8 @@ int usage(char *complaint) fprintf(stderr," [-v ...] [-t request timeout in ms]\n"); fprintf(stderr,"or\n"); fprintf(stderr," dna [-v ...] [-t timeout] -d did -C\n"); + fprintf(stderr,"or\n"); + fprintf(stderr," dna [-v ...] -f -E \n"); fprintf(stderr,"\n"); fprintf(stderr," -v - increase verbosity.\n"); @@ -259,10 +276,26 @@ int main(int argc,char **argv) srandomdev(); - while((c=getopt(argc,argv,"Ab:B:S:f:d:i:l:L:np:P:s:t:vR:W:U:D:CO:")) != -1 ) + while((c=getopt(argc,argv,"Ab:B:E:G:I:S:f:d:i:l:L:np:P:s:t:vR:W:U:D:CO:")) != -1 ) { switch(c) { + case 'G': /* Offer gateway services */ + gatewayuri=strdup(optarg); + break; + case 'E': /* Export HLR into plain text file that can be imported later */ + if (!hlr_file) usage("You must specify an HLR file to export from, i.e., dna -f hlr.dat -E hlr.txt"); + return exportHlr((unsigned char*)hlr_file,optarg); + break; + case 'I': /* Import HLR data from a plain text file into current HLR */ + if (importFile) usage("-I multiply specified."); + importFile=optarg; + if (!hlr_file||!serverMode) usage("-I requires -S and -f."); + if (openHlrFile(hlr_file,hlr_size)) + exit(setReason("Failed to open HLR database")); + importHlr(importFile); + return 0; + break; case 'n': /* don't detach from foreground in server mode */ foregroundMode=1; break; case 'b': /* talk peers on a BATMAN mesh */ diff --git a/export.c b/export.c new file mode 100644 index 00000000..29e9a6d2 --- /dev/null +++ b/export.c @@ -0,0 +1,255 @@ +/* + Export the contents of an binary formatted HLR into plain text. + +*/ + +#include "mphlr.h" + +int nyblValue(int c) +{ + if (c>='0'&&c<='9') return c-'0'; + if (c>='A'&&c<='F') return c-'A'+10; + if (c>='a'&&c<='f') return c-'a'+10; + exit(setReason("Illegal character `%c' in hexadecimal value.",c)); +} + +int importHlr(char *textfile) +{ + int j; + FILE *i; + unsigned char line[1024]; + char sid[128]; + int state=0; + int hofs=-1; + int varinst; + int varid; + int varlen; + unsigned char data[65536]; + int dlen=0; + int linenum=0; + + if (!strcmp("-",textfile)) i=stdin; + else + if ((i=fopen(textfile,"r"))==NULL) exit(setReason("Could not open import file `%s'")); + + line[0]=0; fgets((char *)line,1024,i); + while(!feof(i)) + { + int l=strlen((char *)line); + linenum++; + + /* Strip CR/LFs */ + while(l>0&&(line[l-1]=='\n'||line[l-1]=='\r')) l--; line[l]=0; + + /* Sanity check line */ + for(j=0;j0x7f)&&line[j]!='\n')) { + exit(setReason("Illegal character 0x%02x encountered in line %d of HLR import file.",line[j],linenum)); + } + + if (line[0]!='#') + { + /* Deal with line */ + switch(state) + { + case 0: /* looking for a control line */ + if (!strncmp("sid=",(char *)line,4)) { + /* Read SID, and create HLR record for it if one doesn't already exist */ + if (l!=4+SID_SIZE*2) + exit(setReason("Malformed sid= line encountered in line %d of HLR import file.",linenum)); + + /* Extract SID */ + for(j=0;j0xff) + exit(setReason("%s:%d var= line contains illegal variable ID. " + "Multi-value variables must be in the range 80-ff (hexadecimal)",textfile,linenum)); + if (varinst<0||varinst>0xff) + exit(setReason("%s:%d var= line contains illegal variable instance number. Must be in the range 00-ff (hexadecimal)", + textfile,linenum)); + if (varlen<1||varlen>65534) + exit(setReason("%s:%d var= line contains illegal length. Must be in the range 1-65534.",textfile,linenum)); + + /* Okay, we have a valid variable, lets switch to accumulating its value */ + dlen=0; + state=2; + } + else if (sscanf((char *)line,"var=%02x len=%d",&varid,&varlen)==2) { + if (varid>0x7f||varid<0) + exit(setReason("%s:%d var= line contains illegal variable ID. " + "Single-value variables must be in the range 00-7f (hexadecimal)",textfile,linenum)); + varinst=0; + if (varlen<1||varlen>65534) + exit(setReason("%s:%d var= line contains illegal length. Must be in the range 1-65534.",textfile,linenum)); + + /* Okay, we have a valid variable, lets switch to accumulating its value */ + dlen=0; + state=2; + } else { + exit(setReason("%s:%d Syntax error in HLR record.",textfile,linenum)); + } + break; + case 2: /* Reading a variable value */ + /* Read line of data */ + for(j=0;j=varlen) + exit(setReason("%s:%d Variable value data exceeds stated length.\nThis is what was left after I had taken all I needed: `%s'.",textfile,linenum,&line[j])); + switch(line[j]) + { + case '\\': + j++; + switch(line[j]) + { + case 'n': data[dlen++]='\n'; break; + case 'r': data[dlen++]='\r'; break; + case 'x': data[dlen++]=(hexvalue(line[j+1])<<4)+hexvalue(line[j+2]); j+=2; break; + default: + exit(setReason("%s:%d Illegal \\ sequence `\\%c' encountered in variable value. Only \\r, \\n and \\x are accepted.",textfile,linenum,line[j])); + } + break; + default: + data[dlen++]=line[j]; + } + j++; + } + + if (dlen==varlen) { + state=1; + if (hofs==-1) { + if (varid!=VAR_DIDS||varinst!=0) + { + /* This variable instance is not the first DID, but we still need to create the HLR record. + This is naughty. The first var= line after a sid= line MUST be var=80:00 to specify the first DID. */ + exit(setReason("%s:%d The first var= line after a sid= line MUST be var=80:00 to specify the first DID.",textfile,linenum)); + } + else + { + /* Okay, this is the first DID, so now we can create the HLR record. + But first, we need to unpack the DID into ascii */ + char did[SIDDIDFIELD_LEN+1]; + int zero=0; + extractDid(data,&zero,did); + printf("DID=%s\n",did); + if (createHlr((char *)did,sid)) + exit(setReason("%s:%d createHlr() failed.",textfile,linenum)); + hofs=0; + findHlr(hlr,&hofs,NULL,did); + if (hofs<0) + exit(setReason("%s:%d Could not find created HLR record.",textfile,linenum)); + } + } + + } + } + } + + line[0]=0; fgets((char *)line,1024,i); + } + + fclose(i); + + return 0; +} + +int exportHlr(unsigned char *hlr_file,char *text) +{ + FILE *o; + int ofs=0,i; + if (openHlrFile((char *)hlr_file,-1)) exit(setReason("Could not open HLR database")); + + if (!strcmp("-",text)) o=stdout; + else + if ((o=fopen(text,"w"))==NULL) exit(setReason("Could not create export file")); + + while(findHlr(hlr,&ofs,NULL,NULL)) + { + int hofs=ofs; + fprintf(o,"# HLR Record at 0x%08x\n",ofs); + + /* Output SID for this record */ + fprintf(o,"sid="); + for(i=0;i<32;i++) fprintf(o,"%02x",hlr[hofs+4+i]); + fprintf(o,"\n"); + + struct hlrentry_handle *h=openhlrentry(hlr,hofs); + + while(h) + { + int cols; + if (h->var_id==0&&h->value_len==0) break; + + fprintf(o,"var=%02x",h->var_id); + if (h->var_id&0x80) fprintf(o,":%02x",h->var_instance); + fprintf(o," len=%d",h->value_len); + for(i=0;vars[i].name;i++) if (vars[i].id==h->var_id) { fprintf(o," name=%s",vars[i].name); break; } + fprintf(o,"\n"); + + cols=0; + for (i=0;ivalue_len;i++) + { + if (h->value[i]>=' '&&h->value[i]<=0x7f&&h->value[i]!='\\'&&(cols||h->value[i]!='#')) + { + fprintf(o,"%c",h->value[i]); + cols++; + } + else + { + switch(h->value[i]) { + case '\r': fprintf(o,"\\r"); cols+=2; break; + case '\n': fprintf(o,"\\n"); cols+=2; break; + default: + fprintf(o,"\\x%02x",(unsigned char)h->value[i]); cols+=4; + } + if (cols>75) { fprintf(o,"\n"); cols=0; } + } + } + if (cols) { fprintf(o,"\n"); cols=0; } + + h=hlrentrygetent(h); + } + + /* Mark the end of the record + (as much to make life easier for the import parser as anything) */ + fprintf(o,"eor\n"); + + /* Advance to next record and keep searching */ + if (nextHlr(hlr,&ofs)) break; + } + + return 0; +} diff --git a/hlrdata.c b/hlrdata.c index 5735b185..aa4a46e0 100755 --- a/hlrdata.c +++ b/hlrdata.c @@ -439,3 +439,59 @@ int hlrDump(unsigned char *hlr,int hofs) return 0; } + +int openHlrFile(char *backing_file,int size) +{ + /* Get backing store */ + if (!backing_file) + { + if (size<0) exit(setReason("You must provide an HLR file or size")); + + /* transitory storage of HLR data, so just malloc() the memory */ + hlr=calloc(size,1); + if (!hlr) exit(setReason("Failed to calloc() HLR database.")); + if (debug) fprintf(stderr,"Allocated %d byte temporary HLR store\n",size); + } + else + { + unsigned char zero[8192]; + FILE *f=fopen(backing_file,"r+"); + if (!f) f=fopen(backing_file,"w+"); + if (!f) exit(setReason("Could not open backing file.")); + bzero(&zero[0],8192); + fseek(f,0,SEEK_END); + errno=0; + + /* Obtain size from existing backing file */ + if (size<0) size=ftell(f); + + while(ftell(f)